#include <optional> // for optional
#include <utility> // for move
+#include <QByteArray> // for QByteArray
+#include <QDate> // for QDate
+#include <QTime> // for QTime
#include <QDateTime> // for QDateTime
#include <QDebug> // for QDebug
#include <QList> // for QList, QList<>::const_iterator, QList<>::const_reverse_iterator, QList<>::count, QList<>::reverse_iterator
[[gnu::format(printf, 2, 0)]] int xvasprintf(char** strp, const char* fmt, va_list ap);
char* strupper(char* src);
char* strlower(char* src);
-time_t mklocaltime(std::tm* time);
-time_t mkgmtime(std::tm* time);
+QDateTime make_datetime(QDate date, QTime time, bool is_localtime, bool force_utc, int utc_offset);
bool gpsbabel_testmode();
gpsbabel::DateTime current_time();
QDateTime dotnet_time_to_qdatetime(long long dotnet);
+long long qdatetime_to_dotnet_time(const QDateTime& dt);
QString strip_html(const QString& utfstring);
QString strip_nastyhtml(const QString& in);
QString convert_human_date_format(const char* human_datef); /* "MM,YYYY,DD" -> "%m,%Y,%d" */
--- /dev/null
+lat,lon,iso datetime
+40.000000,-105.070000,1970-01-03T00:04:05-07:00
+40.050000,-105.120000,1970-01-03T05:04:05-07:00
+40.120000,-105.190000,1970-01-04T12:04:05-07:00
+40.170000,-105.000000,1970-01-04T17:04:05-07:00
+40.040000,-105.110000,2069-12-31T04:05:06-07:00
+40.900000,-105.900000,
--- /dev/null
+LAT_DECIMAL,LON_DECIMAL,EXCEL_TIME,GMT_TIME-12HR,GMT_TIME-DATE-24HR,GMT_TIME-24HR,LOCAL_TIME-12HR,LOCAL_TIME-DATE-24HR,LOCAL_TIME-24HR,ISO_TIME,ISO_TIME_MS,NET_TIME,TIMET_TIME,TIMET_TIME_MS,YYYYMMDD_TIME
+40.000000,-105.070000,1970-01-03T07:04:05Z
+40.050000,-105.120000,1970-01-03T12:04:05Z
+40.120000,-105.190000,1970-01-04T19:04:05Z
+40.170000,-105.000000,1970-01-05T00:04:05Z
+40.040000,-105.110000,2069-12-31T11:05:06Z
+40.900000,-105.900000,
--- /dev/null
+LAT_DECIMAL,LON_DECIMAL,EXCEL_TIME,GMT_TIME-12HR,GMT_TIME-DATE-24HR,GMT_TIME-24HR,LOCAL_TIME-12HR,LOCAL_TIME-DATE-24HR,LOCAL_TIME-24HR,ISO_TIME,ISO_TIME_MS,NET_TIME,TIMET_TIME,TIMET_TIME_MS,YYYYMMDD_TIME
+40.000000,-105.070000,2.557129450231e+04,07:04:05 AM,1970-01-03 07:04:05,07:04:05,12:04:05 AM,1970-01-03 00:04:05,00:04:05,1970-01-03T07:04:05Z,1970-01-03T07:04:05Z,621357950450000000,198245,198245000,19700103
+40.050000,-105.120000,2.557150283565e+04,12:04:05 PM,1970-01-03 12:04:05,12:04:05,05:04:05 AM,1970-01-03 05:04:05,05:04:05,1970-01-03T12:04:05Z,1970-01-03T12:04:05Z,621358130450000000,216245,216245000,19700103
+40.120000,-105.190000,2.557279450231e+04,07:04:05 PM,1970-01-04 19:04:05,19:04:05,12:04:05 PM,1970-01-04 12:04:05,12:04:05,1970-01-04T19:04:05Z,1970-01-04T19:04:05Z,621359246450000000,327845,327845000,19700104
+40.170000,-105.000000,2.557300283565e+04,12:04:05 AM,1970-01-05 00:04:05,00:04:05,05:04:05 PM,1970-01-04 17:04:05,17:04:05,1970-01-05T00:04:05Z,1970-01-05T00:04:05Z,621359426450000000,345845,345845000,19700105
+40.040000,-105.110000,6.209346187500e+04,11:05:06 AM,2069-12-31 11:05:06,11:05:06,04:05:06 AM,2069-12-31 04:05:06,04:05:06,2069-12-31T11:05:06Z,2069-12-31T11:05:06Z,652913103060000000,3155713506,3155713506000,20691231
+40.900000,-105.900000,,,,,,,,,,,,,
option xcsv datum GPS datum (def. WGS 84) string https://www.gpsbabel.org/WEB_DOC_DIR/fmt_xcsv.html#fmt_xcsv_o_datum
+option xcsv utc Write timestamps with offset x to UTC time integer -14 +14 https://www.gpsbabel.org/WEB_DOC_DIR/fmt_xcsv.html#fmt_xcsv_o_utc
+
internal rw---- tabsep All database fields on one tab-separated line xcsv
https://www.gpsbabel.org/WEB_DOC_DIR/fmt_tabsep.html
option tabsep snlen Max synthesized shortname length integer 1 https://www.gpsbabel.org/WEB_DOC_DIR/fmt_tabsep.html#fmt_tabsep_o_snlen
option tabsep datum GPS datum (def. WGS 84) string https://www.gpsbabel.org/WEB_DOC_DIR/fmt_tabsep.html#fmt_tabsep_o_datum
+option tabsep utc Write timestamps with offset x to UTC time integer -14 +14 https://www.gpsbabel.org/WEB_DOC_DIR/fmt_tabsep.html#fmt_tabsep_o_utc
+
file r-r--- v900 Columbus/Visiontac V900 files (.csv) v900
https://www.gpsbabel.org/WEB_DOC_DIR/fmt_v900.html
file rw---- csv Comma separated values xcsv
option csv datum GPS datum (def. WGS 84) string https://www.gpsbabel.org/WEB_DOC_DIR/fmt_csv.html#fmt_csv_o_datum
+option csv utc Write timestamps with offset x to UTC time integer -14 +14 https://www.gpsbabel.org/WEB_DOC_DIR/fmt_csv.html#fmt_csv_o_utc
+
internal rw---- custom Custom "Everything" Style xcsv
https://www.gpsbabel.org/WEB_DOC_DIR/fmt_custom.html
option custom snlen Max synthesized shortname length integer 1 https://www.gpsbabel.org/WEB_DOC_DIR/fmt_custom.html#fmt_custom_o_snlen
option custom datum GPS datum (def. WGS 84) string https://www.gpsbabel.org/WEB_DOC_DIR/fmt_custom.html#fmt_custom_o_datum
+option custom utc Write timestamps with offset x to UTC time integer -14 +14 https://www.gpsbabel.org/WEB_DOC_DIR/fmt_custom.html#fmt_custom_o_utc
+
file --rw-- iblue747 csv Data Logger iBlue747 csv xcsv
https://www.gpsbabel.org/WEB_DOC_DIR/fmt_iblue747.html
option iblue747 snlen Max synthesized shortname length integer 1 https://www.gpsbabel.org/WEB_DOC_DIR/fmt_iblue747.html#fmt_iblue747_o_snlen
option iblue747 datum GPS datum (def. WGS 84) string https://www.gpsbabel.org/WEB_DOC_DIR/fmt_iblue747.html#fmt_iblue747_o_datum
+option iblue747 utc Write timestamps with offset x to UTC time integer -14 +14 https://www.gpsbabel.org/WEB_DOC_DIR/fmt_iblue747.html#fmt_iblue747_o_utc
+
file --rw-- iblue757 csv Data Logger iBlue757 csv xcsv
https://www.gpsbabel.org/WEB_DOC_DIR/fmt_iblue757.html
option iblue757 snlen Max synthesized shortname length integer 1 https://www.gpsbabel.org/WEB_DOC_DIR/fmt_iblue757.html#fmt_iblue757_o_snlen
option iblue757 datum GPS datum (def. WGS 84) string https://www.gpsbabel.org/WEB_DOC_DIR/fmt_iblue757.html#fmt_iblue757_o_datum
+option iblue757 utc Write timestamps with offset x to UTC time integer -14 +14 https://www.gpsbabel.org/WEB_DOC_DIR/fmt_iblue757.html#fmt_iblue757_o_utc
+
file rw---- exif jpg Embedded Exif-GPS data (.jpg) exif
https://www.gpsbabel.org/WEB_DOC_DIR/fmt_exif.html
option exif filename Set waypoint name to source filename boolean Y https://www.gpsbabel.org/WEB_DOC_DIR/fmt_exif.html#fmt_exif_o_filename
option garmin301 datum GPS datum (def. WGS 84) string https://www.gpsbabel.org/WEB_DOC_DIR/fmt_garmin301.html#fmt_garmin301_o_datum
+option garmin301 utc Write timestamps with offset x to UTC time integer -14 +14 https://www.gpsbabel.org/WEB_DOC_DIR/fmt_garmin301.html#fmt_garmin301_o_utc
+
file --rw-- garmin_g1000 csv Garmin G1000 datalog input filter file xcsv
https://www.gpsbabel.org/WEB_DOC_DIR/fmt_garmin_g1000.html
option garmin_g1000 snlen Max synthesized shortname length integer 1 https://www.gpsbabel.org/WEB_DOC_DIR/fmt_garmin_g1000.html#fmt_garmin_g1000_o_snlen
option garmin_g1000 datum GPS datum (def. WGS 84) string https://www.gpsbabel.org/WEB_DOC_DIR/fmt_garmin_g1000.html#fmt_garmin_g1000_o_datum
+option garmin_g1000 utc Write timestamps with offset x to UTC time integer -14 +14 https://www.gpsbabel.org/WEB_DOC_DIR/fmt_garmin_g1000.html#fmt_garmin_g1000_o_utc
+
file rwrwrw gdb gdb Garmin MapSource - gdb gdb
https://www.gpsbabel.org/WEB_DOC_DIR/fmt_gdb.html
option gdb cat Default category on output (1..16) integer 1 16 https://www.gpsbabel.org/WEB_DOC_DIR/fmt_gdb.html#fmt_gdb_o_cat
option garmin_poi datum GPS datum (def. WGS 84) string https://www.gpsbabel.org/WEB_DOC_DIR/fmt_garmin_poi.html#fmt_garmin_poi_o_datum
+option garmin_poi utc Write timestamps with offset x to UTC time integer -14 +14 https://www.gpsbabel.org/WEB_DOC_DIR/fmt_garmin_poi.html#fmt_garmin_poi_o_utc
+
file rw---- garmin_gpi gpi Garmin Points of Interest (.gpi) garmin_gpi
https://www.gpsbabel.org/WEB_DOC_DIR/fmt_garmin_gpi.html
option garmin_gpi alerts Enable alerts on speed or proximity distance boolean https://www.gpsbabel.org/WEB_DOC_DIR/fmt_garmin_gpi.html#fmt_garmin_gpi_o_alerts
option land_air_sea datum GPS datum (def. WGS 84) string https://www.gpsbabel.org/WEB_DOC_DIR/fmt_land_air_sea.html#fmt_land_air_sea_o_datum
+option land_air_sea utc Write timestamps with offset x to UTC time integer -14 +14 https://www.gpsbabel.org/WEB_DOC_DIR/fmt_land_air_sea.html#fmt_land_air_sea_o_utc
+
file rwrwrw gtm gtm GPS TrackMaker gtm
https://www.gpsbabel.org/WEB_DOC_DIR/fmt_gtm.html
file rw---- arc txt GPSBabel arc filter file xcsv
option arc datum GPS datum (def. WGS 84) string https://www.gpsbabel.org/WEB_DOC_DIR/fmt_arc.html#fmt_arc_o_datum
+option arc utc Write timestamps with offset x to UTC time integer -14 +14 https://www.gpsbabel.org/WEB_DOC_DIR/fmt_arc.html#fmt_arc_o_utc
+
file rw---- gpsdrive GpsDrive Format xcsv
https://www.gpsbabel.org/WEB_DOC_DIR/fmt_gpsdrive.html
option gpsdrive snlen Max synthesized shortname length integer 1 https://www.gpsbabel.org/WEB_DOC_DIR/fmt_gpsdrive.html#fmt_gpsdrive_o_snlen
option gpsdrive datum GPS datum (def. WGS 84) string https://www.gpsbabel.org/WEB_DOC_DIR/fmt_gpsdrive.html#fmt_gpsdrive_o_datum
+option gpsdrive utc Write timestamps with offset x to UTC time integer -14 +14 https://www.gpsbabel.org/WEB_DOC_DIR/fmt_gpsdrive.html#fmt_gpsdrive_o_utc
+
file rw---- gpsdrivetrack GpsDrive Format for Tracks xcsv
https://www.gpsbabel.org/WEB_DOC_DIR/fmt_gpsdrivetrack.html
option gpsdrivetrack snlen Max synthesized shortname length integer 1 https://www.gpsbabel.org/WEB_DOC_DIR/fmt_gpsdrivetrack.html#fmt_gpsdrivetrack_o_snlen
option gpsdrivetrack datum GPS datum (def. WGS 84) string https://www.gpsbabel.org/WEB_DOC_DIR/fmt_gpsdrivetrack.html#fmt_gpsdrivetrack_o_datum
+option gpsdrivetrack utc Write timestamps with offset x to UTC time integer -14 +14 https://www.gpsbabel.org/WEB_DOC_DIR/fmt_gpsdrivetrack.html#fmt_gpsdrivetrack_o_utc
+
file rwrwrw gpx gpx GPX XML gpx
https://www.gpsbabel.org/WEB_DOC_DIR/fmt_gpx.html
option gpx snlen Length of generated shortnames integer 32 1 https://www.gpsbabel.org/WEB_DOC_DIR/fmt_gpx.html#fmt_gpx_o_snlen
option openoffice datum GPS datum (def. WGS 84) string https://www.gpsbabel.org/WEB_DOC_DIR/fmt_openoffice.html#fmt_openoffice_o_datum
+option openoffice utc Write timestamps with offset x to UTC time integer -14 +14 https://www.gpsbabel.org/WEB_DOC_DIR/fmt_openoffice.html#fmt_openoffice_o_utc
+
file -w---- text txt Textual Output text
https://www.gpsbabel.org/WEB_DOC_DIR/fmt_text.html
option text nosep Suppress separator lines between waypoints boolean https://www.gpsbabel.org/WEB_DOC_DIR/fmt_text.html#fmt_text_o_nosep
option unicsv grid Write position using this grid. string https://www.gpsbabel.org/WEB_DOC_DIR/fmt_unicsv.html#fmt_unicsv_o_grid
-option unicsv utc Write timestamps with offset x to UTC time integer -23 +23 https://www.gpsbabel.org/WEB_DOC_DIR/fmt_unicsv.html#fmt_unicsv_o_utc
+option unicsv utc Write timestamps with offset x to UTC time integer -14 +14 https://www.gpsbabel.org/WEB_DOC_DIR/fmt_unicsv.html#fmt_unicsv_o_utc
option unicsv format Write name(s) of format(s) from input session(s) boolean https://www.gpsbabel.org/WEB_DOC_DIR/fmt_unicsv.html#fmt_unicsv_o_format
urlbase Basename prepended to URL on output
prefer_shortnames (0/1) Use shortname instead of description
datum GPS datum (def. WGS 84)
+ utc Write timestamps with offset x to UTC time
iblue747 Data Logger iBlue747 csv
snlen Max synthesized shortname length
snwhite (0/1) Allow whitespace synth. shortnames
urlbase Basename prepended to URL on output
prefer_shortnames (0/1) Use shortname instead of description
datum GPS datum (def. WGS 84)
+ utc Write timestamps with offset x to UTC time
iblue757 Data Logger iBlue757 csv
snlen Max synthesized shortname length
snwhite (0/1) Allow whitespace synth. shortnames
urlbase Basename prepended to URL on output
prefer_shortnames (0/1) Use shortname instead of description
datum GPS datum (def. WGS 84)
+ utc Write timestamps with offset x to UTC time
exif Embedded Exif-GPS data (.jpg)
filename (0/1) Set waypoint name to source filename
frame Time-frame (in seconds)
urlbase Basename prepended to URL on output
prefer_shortnames (0/1) Use shortname instead of description
datum GPS datum (def. WGS 84)
+ utc Write timestamps with offset x to UTC time
garmin_g1000 Garmin G1000 datalog input filter file
snlen Max synthesized shortname length
snwhite (0/1) Allow whitespace synth. shortnames
urlbase Basename prepended to URL on output
prefer_shortnames (0/1) Use shortname instead of description
datum GPS datum (def. WGS 84)
+ utc Write timestamps with offset x to UTC time
gdb Garmin MapSource - gdb
cat Default category on output (1..16)
bitscategory Bitmap of categories
urlbase Basename prepended to URL on output
prefer_shortnames (0/1) Use shortname instead of description
datum GPS datum (def. WGS 84)
+ utc Write timestamps with offset x to UTC time
garmin_gpi Garmin Points of Interest (.gpi)
alerts (0/1) Enable alerts on speed or proximity distance
bitmap Use specified bitmap on output
urlbase Basename prepended to URL on output
prefer_shortnames (0/1) Use shortname instead of description
datum GPS datum (def. WGS 84)
+ utc Write timestamps with offset x to UTC time
gtm GPS TrackMaker
arc GPSBabel arc filter file
snlen Max synthesized shortname length
urlbase Basename prepended to URL on output
prefer_shortnames (0/1) Use shortname instead of description
datum GPS datum (def. WGS 84)
+ utc Write timestamps with offset x to UTC time
gpsdrive GpsDrive Format
snlen Max synthesized shortname length
snwhite (0/1) Allow whitespace synth. shortnames
urlbase Basename prepended to URL on output
prefer_shortnames (0/1) Use shortname instead of description
datum GPS datum (def. WGS 84)
+ utc Write timestamps with offset x to UTC time
gpsdrivetrack GpsDrive Format for Tracks
snlen Max synthesized shortname length
snwhite (0/1) Allow whitespace synth. shortnames
urlbase Basename prepended to URL on output
prefer_shortnames (0/1) Use shortname instead of description
datum GPS datum (def. WGS 84)
+ utc Write timestamps with offset x to UTC time
gpx GPX XML
snlen Length of generated shortnames
suppresswhite (0/1) No whitespace in generated shortnames
urlbase Basename prepended to URL on output
prefer_shortnames (0/1) Use shortname instead of description
datum GPS datum (def. WGS 84)
+ utc Write timestamps with offset x to UTC time
text Textual Output
nosep (0/1) Suppress separator lines between waypoints
encrypt (0/1) Encrypt hints using ROT13
--- /dev/null
+No,Latitude,Longitude,Name,Date,Time\r
+1,40.000000,-105.000000,"WPT001",1970/01/03,03:04:05\r
+2,40.100000,-105.100000,"WPT002",2069/12/31,04:05:06\r
--- /dev/null
+40.000000,-105.000000,1970-01-03,03:04:05,1970-01-03T03:04:05-07:00
+40.100000,-105.100000,2069-12-31,04:05:06,2069-12-31T04:05:06-07:00
--28.606309,41.491196,85.918,Wpt_RD,1970-01-01T00:00:00Z
+-28.606309,41.491196,85.918,Wpt_RD,
-28.605513,41.492136,0.027,Wpt_ahVv,1970-01-01T00:00:01.189Z
-28.605013,41.492918,78.576,Wpt_ElFRt5,1970-01-01T00:00:02.317Z
-28.604849,41.492946,,Wpt_Stg4W,1970-01-01T00:00:04.160Z
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<gpx version="1.0" creator="GPSBabel - https://www.gpsbabel.org" xmlns="http://www.topografix.com/GPX/1/0">
+ <time>1970-01-01T00:00:00Z</time>
+ <bounds minlat="36.000000000" minlon="-87.000000000" maxlat="36.000000000" maxlon="-87.000000000"/>
+ <wpt lat="36.000000000" lon="-87.000000000">
+ <time>2022-01-10T23:00:00Z</time>
+ <name>WPT001</name>
+ <cmt>WPT001</cmt>
+ <desc>WPT001</desc>
+ </wpt>
+ <wpt lat="36.000000000" lon="-87.000000000">
+ <time>2022-07-10T23:00:00Z</time>
+ <name>WPT001</name>
+ <cmt>WPT001</cmt>
+ <desc>WPT001</desc>
+ </wpt>
+ <wpt lat="36.000000000" lon="-87.000000000">
+ <time>1970-01-01T23:00:00Z</time>
+ <name>WPT002</name>
+ <cmt>WPT002</cmt>
+ <desc>WPT002</desc>
+ </wpt>
+ <wpt lat="36.000000000" lon="-87.000000000">
+ <time>2022-01-10T00:00:00Z</time>
+ <name>WPT002</name>
+ <cmt>WPT002</cmt>
+ <desc>WPT002</desc>
+ </wpt>
+ <wpt lat="36.000000000" lon="-87.000000000">
+ <time>2022-07-10T00:00:00Z</time>
+ <name>WPT002</name>
+ <cmt>WPT002</cmt>
+ <desc>WPT002</desc>
+ </wpt>
+</gpx>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<gpx version="1.0" creator="GPSBabel - https://www.gpsbabel.org" xmlns="http://www.topografix.com/GPX/1/0">
+ <time>1970-01-01T00:00:00Z</time>
+ <bounds minlat="36.000000000" minlon="-87.000000000" maxlat="36.000000000" maxlon="-87.000000000"/>
+ <wpt lat="36.000000000" lon="-87.000000000">
+ <time>2022-01-10T22:00:00Z</time>
+ <name>WPT001</name>
+ <cmt>WPT001</cmt>
+ <desc>WPT001</desc>
+ </wpt>
+ <wpt lat="36.000000000" lon="-87.000000000">
+ <time>2022-07-10T22:00:00Z</time>
+ <name>WPT001</name>
+ <cmt>WPT001</cmt>
+ <desc>WPT001</desc>
+ </wpt>
+ <wpt lat="36.000000000" lon="-87.000000000">
+ <time>1970-01-01T22:00:00Z</time>
+ <name>WPT002</name>
+ <cmt>WPT002</cmt>
+ <desc>WPT002</desc>
+ </wpt>
+ <wpt lat="36.000000000" lon="-87.000000000">
+ <time>2022-01-09T23:00:00Z</time>
+ <name>WPT002</name>
+ <cmt>WPT002</cmt>
+ <desc>WPT002</desc>
+ </wpt>
+ <wpt lat="36.000000000" lon="-87.000000000">
+ <time>2022-07-09T23:00:00Z</time>
+ <name>WPT002</name>
+ <cmt>WPT002</cmt>
+ <desc>WPT002</desc>
+ </wpt>
+</gpx>
--- /dev/null
+No,Latitude,Longitude,Name,Date,Time\r
+1,36.000000,-87.000000,"WPT001",2022/01/10,23:00:00\r
+2,36.000000,-87.000000,"WPT001",2022/07/10,23:00:00\r
+3,36.000000,-87.000000,"WPT002",,23:00:00\r
+4,36.000000,-87.000000,"WPT002",2022/01/10,\r
+5,36.000000,-87.000000,"WPT002",2022/07/10,\r
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<gpx version="1.0" creator="GPSBabel - https://www.gpsbabel.org" xmlns="http://www.topografix.com/GPX/1/0">
+ <time>1970-01-01T00:00:00Z</time>
+ <bounds minlat="36.000000000" minlon="-87.000000000" maxlat="36.000000000" maxlon="-87.000000000"/>
+ <wpt lat="36.000000000" lon="-87.000000000">
+ <time>2022-01-11T07:00:00Z</time>
+ <name>WPT001</name>
+ <cmt>WPT001</cmt>
+ <desc>WPT001</desc>
+ </wpt>
+ <wpt lat="36.000000000" lon="-87.000000000">
+ <time>2022-07-11T06:00:00Z</time>
+ <name>WPT001</name>
+ <cmt>WPT001</cmt>
+ <desc>WPT001</desc>
+ </wpt>
+ <wpt lat="36.000000000" lon="-87.000000000">
+ <time>1970-01-02T07:00:00Z</time>
+ <name>WPT002</name>
+ <cmt>WPT002</cmt>
+ <desc>WPT002</desc>
+ </wpt>
+ <wpt lat="36.000000000" lon="-87.000000000">
+ <time>2022-01-10T08:00:00Z</time>
+ <name>WPT002</name>
+ <cmt>WPT002</cmt>
+ <desc>WPT002</desc>
+ </wpt>
+ <wpt lat="36.000000000" lon="-87.000000000">
+ <time>2022-07-10T07:00:00Z</time>
+ <name>WPT002</name>
+ <cmt>WPT002</cmt>
+ <desc>WPT002</desc>
+ </wpt>
+</gpx>
--- /dev/null
+No,Latitude,Longitude,Name,Date,Time\r
+1,36.000000,-87.000000,"WPT001",2022/01/10,23:00:00\r
+2,36.000000,-87.000000,"WPT001",2022/07/10,23:00:00\r
+3,36.000000,-87.000000,"WPT002",,23:00:00\r
+4,36.000000,-87.000000,"WPT002",2022/01/10,00:00:00\r
+5,36.000000,-87.000000,"WPT002",2022/07/10,00:00:00\r
--- /dev/null
+No,Latitude,Longitude,Name,Date,Time\r
+1,36.000000,-87.000000,"WPT001",2022/01/10,23:00:00\r
+2,36.000000,-87.000000,"WPT001",2022/07/10,23:00:00\r
+3,36.000000,-87.000000,"WPT002",,23:00:00\r
+4,36.000000,-87.000000,"WPT002",2022/01/10,00:00:00\r
+5,36.000000,-87.000000,"WPT002",2022/07/10,00:00:00\r
--- /dev/null
+No,Latitude,Longitude,Name,utc_d,utc_t\r
+1,36.000000,-87.000000,"WPT001",2022/01/10,23:00:00\r
+2,36.000000,-87.000000,"WPT001",2022/07/10,23:00:00\r
+3,36.000000,-87.000000,"WPT002",,23:00:00\r
+4,36.000000,-87.000000,"WPT002",2022/01/10,\r
+5,36.000000,-87.000000,"WPT002",2022/07/10,\r
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<gpx version="1.0" creator="GPSBabel - https://www.gpsbabel.org" xmlns="http://www.topografix.com/GPX/1/0">
+ <time>1970-01-01T00:00:00Z</time>
+ <bounds minlat="36.000000000" minlon="-87.000000000" maxlat="36.000000000" maxlon="-87.000000000"/>
+ <wpt lat="36.000000000" lon="-87.000000000">
+ <time>2022-01-10T23:00:00Z</time>
+ <name>WPT001</name>
+ <cmt>WPT001</cmt>
+ <desc>WPT001</desc>
+ </wpt>
+ <wpt lat="36.000000000" lon="-87.000000000">
+ <time>2022-07-10T23:00:00Z</time>
+ <name>WPT001</name>
+ <cmt>WPT001</cmt>
+ <desc>WPT001</desc>
+ </wpt>
+ <wpt lat="36.000000000" lon="-87.000000000">
+ <time>1970-01-01T23:00:00Z</time>
+ <name>WPT002</name>
+ <cmt>WPT002</cmt>
+ <desc>WPT002</desc>
+ </wpt>
+ <wpt lat="36.000000000" lon="-87.000000000">
+ <time>2022-01-10T00:00:00Z</time>
+ <name>WPT002</name>
+ <cmt>WPT002</cmt>
+ <desc>WPT002</desc>
+ </wpt>
+ <wpt lat="36.000000000" lon="-87.000000000">
+ <time>2022-07-10T00:00:00Z</time>
+ <name>WPT002</name>
+ <cmt>WPT002</cmt>
+ <desc>WPT002</desc>
+ </wpt>
+</gpx>
# INDIVIDUAL DATA FIELDS:
#
IFIELD GMT_TIME,"","%Y-%m-%d" #Lcl Date,
-IFIELD HMSG_TIME,"","%d:%d:%d %s" #Lcl Time,
+IFIELD GMT_TIME,"","%H:%M:%S" #Lcl Time,
IFIELD IGNORE,"","%s" #UTCOfst,
IFIELD IGNORE,"","%s" #AtvWpt,
IFIELD LAT_DECIMAL, "", "%f" #Latitude,
IFIELD INDEX,"1","%d" # INDEX
IFIELD CONSTANT,"T","%s" # RCR
IFIELD GMT_TIME,"","%Y/%m/%d" # DATE
-IFIELD HMSG_TIME,"","%02d:%02d:%02d" # TIME
+IFIELD GMT_TIME,"","%H:%M:%S" # TIME
IFIELD GPS_FIX,"","%s" # VALID # No fix, SPS, DGPS, PPS
IFIELD LAT_DECIMAL,"","%f" # LATITUDE
IFIELD LAT_DIR,"","%c" # N/S
IFIELD INDEX,"1","%d" # INDEX
IFIELD CONSTANT,"T","%s" # RCR
IFIELD GMT_TIME,"","%d/%m/%Y" # DATE
-IFIELD HMSG_TIME,"","%02d:%02d:%02d" # TIME
+IFIELD GMT_TIME,"","%H:%M:%S" # TIME
IFIELD GPS_FIX,"","%s" # VALID # No fix, SPS, DGPS, PPS
IFIELD LAT_DECIMAL,"","%f" # LATITUDE
IFIELD LAT_DIR,"","%c" # N/S
# Individual data fields in order of appearance
IFIELD LOCAL_TIME,"","%m-%d-%Y"
-IFIELD HMSG_TIME,"","%d:%d:%d"
+IFIELD LOCAL_TIME,"","%H:%M:%S"
IFIELD LAT_HUMAN_READABLE,"","%c %d°%d'%f\""
IFIELD LON_HUMAN_READABLE,"","%c %d°%d'%f\""
IFIELD PATH_SPEED_MPH,"","%.1fmph"
# Exercise the 'faketime' filter. The middle of the three points has
# time so we can exercise the 'forced' option, too.
-gpsbabel -t -i unicsv -f ${REFERENCE}/track/trackfilter_faketime.txt -x track,faketime=20100506060000+5 -o gpx -F ${TMPDIR}/ft.gpx
+gpsbabel -t -i unicsv,utc -f ${REFERENCE}/track/trackfilter_faketime.txt -x track,faketime=20100506060000+5 -o gpx -F ${TMPDIR}/ft.gpx
compare ${REFERENCE}/track/trackfilter_faketime.gpx ${TMPDIR}/ft.gpx
gpsbabel -t -i unicsv -f ${REFERENCE}/track/trackfilter_faketime.txt -x track,faketime=f20100506060000+5 -o gpx -F ${TMPDIR}/ftf.gpx
compare ${REFERENCE}/track/trackfilter_faketime_forced.gpx ${TMPDIR}/ftf.gpx
--- /dev/null
+if command -v tzselect >/dev/null 2>&1 ; then
+ export TZ='America/Los_Angeles'
+
+ echo " including local timezone tests"
+ # test interpretation of local date and time,
+ # with and without optional utc override, with and without offsets.
+ # these gpx files erroneously show the invented 1970/01/01 date.
+ gpsbabel -i unicsv -f ${REFERENCE}/unicsv-local.csv -o gpx -F ${TMPDIR}/unicsv-local.gpx
+ compare ${REFERENCE}/unicsv-local.gpx ${TMPDIR}/unicsv-local.gpx
+ gpsbabel -i unicsv,utc -f ${REFERENCE}/unicsv-local.csv -o gpx -F ${TMPDIR}/unicsv-local-utc.gpx
+ compare ${REFERENCE}/unicsv-local-utc.gpx ${TMPDIR}/unicsv-local-utc.gpx
+ gpsbabel -i unicsv,utc=1 -f ${REFERENCE}/unicsv-local.csv -o gpx -F ${TMPDIR}/unicsv-local-utc1.gpx
+ compare ${REFERENCE}/unicsv-local-utc1.gpx ${TMPDIR}/unicsv-local-utc1.gpx
+
+ # test display of local date and time,
+ # with and without optional utc override, with and without offsets.
+ gpsbabel -i gpx -f ${REFERENCE}/unicsv-local.gpx -o unicsv -F ${TMPDIR}/unicsv-local~gpx.csv
+ compare ${REFERENCE}/unicsv-local~gpx.csv ${TMPDIR}/unicsv-local~gpx.csv
+ gpsbabel -i gpx -f ${REFERENCE}/unicsv-local-utc.gpx -o unicsv,utc -F ${TMPDIR}/unicsv-local-utc~gpx.csv
+ compare ${REFERENCE}/unicsv-local~gpx.csv ${TMPDIR}/unicsv-local-utc~gpx.csv
+ gpsbabel -i gpx -f ${REFERENCE}/unicsv-local-utc1.gpx -o unicsv,utc=1 -F ${TMPDIR}/unicsv-local-utc1~gpx.csv
+ compare ${REFERENCE}/unicsv-local~gpx.csv ${TMPDIR}/unicsv-local-utc1~gpx.csv
+
+ # test echo of local date and time,
+ # with and without optional utc override, with and without offsets.
+ gpsbabel -i unicsv -f ${REFERENCE}/unicsv-local.csv -o unicsv -F ${TMPDIR}/unicsv-local~csv.csv
+ compare ${REFERENCE}/unicsv-local~csv.csv ${TMPDIR}/unicsv-local~csv.csv
+ gpsbabel -i unicsv,utc -f ${REFERENCE}/unicsv-local.csv -o unicsv,utc -F ${TMPDIR}/unicsv-local-utc~csv.csv
+ compare ${REFERENCE}/unicsv-local~csv.csv ${TMPDIR}/unicsv-local-utc~csv.csv
+ gpsbabel -i unicsv,utc=1 -f ${REFERENCE}/unicsv-local.csv -o unicsv,utc=1 -F ${TMPDIR}/unicsv-local-utc1~csv.csv
+ compare ${REFERENCE}/unicsv-local~csv.csv ${TMPDIR}/unicsv-local-utc1~csv.csv
+
+ unset -v TZ
+fi
+
+# make sure utc_d, utc_t ignore utc option - it only overrides local times.
+gpsbabel -i unicsv -f ${REFERENCE}/unicsv-utc.csv -o gpx -F ${TMPDIR}/unicsv-utc.gpx
+compare ${REFERENCE}/unicsv-utc.gpx ${TMPDIR}/unicsv-utc.gpx
+gpsbabel -i unicsv,utc -f ${REFERENCE}/unicsv-utc.csv -o gpx -F ${TMPDIR}/unicsv-utc-utc.gpx
+compare ${REFERENCE}/unicsv-utc.gpx ${TMPDIR}/unicsv-utc-utc.gpx
+gpsbabel -i unicsv,utc=1 -f ${REFERENCE}/unicsv-utc.csv -o gpx -F ${TMPDIR}/unicsv-utc-utc1.gpx
+compare ${REFERENCE}/unicsv-utc.gpx ${TMPDIR}/unicsv-utc-utc1.gpx
+
echo "IFIELD ALT_METERS, -99999999.0, %.0f" >> ${TMPDIR}/testo2.style
echo "IFIELD IGNORE, , %s" >> ${TMPDIR}/testo2.style
echo "IFIELD GMT_TIME, , %Y/%m/%d" >> ${TMPDIR}/testo2.style
-echo "IFIELD HMSG_TIME, , %d:%d:%d" >> ${TMPDIR}/testo2.style
+echo "IFIELD GMT_TIME, , %H:%M:%S" >> ${TMPDIR}/testo2.style
rm -f ${TMPDIR}/grid-utm~xscv.gpx
gpsbabel -i xcsv,style=${TMPDIR}/testo2.style -f ${REFERENCE}/grid-utm.csv -o gpx -F ${TMPDIR}/grid-utm~xscv.gpx
compare ${REFERENCE}/grid-utm~xscv.gpx ${TMPDIR}/grid-utm~xscv.gpx
# test TRACK_NAME, TRACK_NEW
-echo 'DESCRIPTION track style test 1' >>${TMPDIR}/track1.style
+echo 'DESCRIPTION track style test 1' >${TMPDIR}/track1.style
echo 'EXTENSION csv' >>${TMPDIR}/track1.style
echo 'FIELD_DELIMITER COMMA' >>${TMPDIR}/track1.style
echo 'RECORD_DELIMITER NEWLINE' >>${TMPDIR}/track1.style
compare ${REFERENCE}/track/track1-2~csv.gpx ${TMPDIR}/track1~csv.gpx
# flip TRACK_NAME, TRACK_NEW order
-echo 'DESCRIPTION track style test 2' >>${TMPDIR}/track2.style
+echo 'DESCRIPTION track style test 2' >${TMPDIR}/track2.style
echo 'EXTENSION csv' >>${TMPDIR}/track2.style
echo 'FIELD_DELIMITER COMMA' >>${TMPDIR}/track2.style
echo 'RECORD_DELIMITER NEWLINE' >>${TMPDIR}/track2.style
compare ${REFERENCE}/track/track1-2~csv.gpx ${TMPDIR}/track2~csv.gpx
# ROUTE_NAME
-echo 'DESCRIPTION route style test 1' >>${TMPDIR}/route1.style
+echo 'DESCRIPTION route style test 1' >${TMPDIR}/route1.style
echo 'EXTENSION csv' >>${TMPDIR}/route1.style
echo 'FIELD_DELIMITER COMMA' >>${TMPDIR}/route1.style
echo 'RECORD_DELIMITER NEWLINE' >>${TMPDIR}/route1.style
compare ${REFERENCE}/route/route1~csv.gpx ${TMPDIR}/route1~csv.gpx
# gmsd fields
-echo 'DESCRIPTION gmsd test' >> ${TMPDIR}/gmsd.style
+echo 'DESCRIPTION gmsd test' > ${TMPDIR}/gmsd.style
echo 'EXTENSION csv' >> ${TMPDIR}/gmsd.style
echo 'FIELD_DELIMITER TAB' >> ${TMPDIR}/gmsd.style
echo 'RECORD_DELIMITER NEWLINE' >> ${TMPDIR}/gmsd.style
compare ${REFERENCE}/gmsd.xcsv ${TMPDIR}/gmsd.xcsv
gpsbabel -i xcsv,style=${TMPDIR}/gmsd.style -f ${REFERENCE}/gmsd.xcsv -o unicsv -F ${TMPDIR}/gmsd.unicsv
compare ${REFERENCE}/gmsd.unicsv ${TMPDIR}/gmsd.unicsv
+
+if command -v tzselect >/dev/null 2>&1 ; then
+ export TZ='America/Denver'
+ echo " including xcsv timezone conversion test"
+
+# xcsv writer time handling
+ echo 'FIELD_DELIMITER COMMA' > ${TMPDIR}/datetime.style
+ echo 'RECORD_DELIMITER NEWLINE' >> ${TMPDIR}/datetime.style
+ echo 'PROLOGUE LAT_DECIMAL,LON_DECIMAL,EXCEL_TIME,GMT_TIME-12HR,GMT_TIME-DATE-24HR,GMT_TIME-24HR,LOCAL_TIME-12HR,LOCAL_TIME-DATE-24HR,LOCAL_TIME-24HR,ISO_TIME,ISO_TIME_MS,NET_TIME,TIMET_TIME,TIMET_TIME_MS,YYYYMMDD_TIME' >> ${TMPDIR}/datetime.style
+ echo 'IFIELD LAT_DECIMAL,"","%.6f"' >> ${TMPDIR}/datetime.style
+ echo 'IFIELD LON_DECIMAL,"","%.6f"' >> ${TMPDIR}/datetime.style
+ echo 'IFIELD ISO_TIME, "", "%s"' >> ${TMPDIR}/datetime.style
+ echo 'OFIELD LAT_DECIMAL,"","%.6f"' >> ${TMPDIR}/datetime.style
+ echo 'OFIELD LON_DECIMAL,"","%.6f"' >> ${TMPDIR}/datetime.style
+ echo 'OFIELD EXCEL_TIME, "", "%.12e"' >> ${TMPDIR}/datetime.style
+ echo 'OFIELD GMT_TIME, "", "%I:%M:%S %p"' >> ${TMPDIR}/datetime.style
+ echo 'OFIELD GMT_TIME, "", "%Y-%m-%d %H:%M:%S"' >> ${TMPDIR}/datetime.style
+ echo 'OFIELD GMT_TIME, "", "%H:%M:%S"' >> ${TMPDIR}/datetime.style
+ echo 'OFIELD LOCAL_TIME, "", "%I:%M:%S %p"' >> ${TMPDIR}/datetime.style
+ echo 'OFIELD LOCAL_TIME, "", "%Y-%m-%d %H:%M:%S"' >> ${TMPDIR}/datetime.style
+ echo 'OFIELD LOCAL_TIME, "", "%H:%M:%S"' >> ${TMPDIR}/datetime.style
+ echo 'OFIELD ISO_TIME, "", "%s"' >> ${TMPDIR}/datetime.style
+ echo 'OFIELD ISO_TIME_MS, "", "%s"' >> ${TMPDIR}/datetime.style
+ echo 'OFIELD NET_TIME, "", "%lld"' >> ${TMPDIR}/datetime.style
+ echo 'OFIELD TIMET_TIME, "", "%lld"' >> ${TMPDIR}/datetime.style
+ echo 'OFIELD TIMET_TIME_MS, "", "%lld"' >> ${TMPDIR}/datetime.style
+ echo 'OFIELD YYYYMMDD_TIME, "", "%ld"' >> ${TMPDIR}/datetime.style
+ gpsbabel -i xcsv,style=${TMPDIR}/datetime.style -f ${REFERENCE}/datetime.xcsv -o xcsv,style=${TMPDIR}/datetime.style -F ${TMPDIR}/datetime~xcsv.xcsv
+ compare ${REFERENCE}/datetime~xcsv.xcsv ${TMPDIR}/datetime~xcsv.xcsv
+
+# xcsv reader time handling
+
+ echo 'FIELD_DELIMITER COMMA' > ${TMPDIR}/datetime_excel.style
+ echo 'RECORD_DELIMITER NEWLINE' >> ${TMPDIR}/datetime_excel.style
+ echo 'PROLOGUE LAT_DECIMAL,LON_DECIMAL,EXCEL_TIME,GMT_TIME-12HR,GMT_TIME-DATE-24HR,GMT_TIME-24HR,LOCAL_TIME-12HR,LOCAL_TIME-DATE-24HR,LOCAL_TIME-24HR,ISO_TIME,ISO_TIME_MS,NET_TIME,TIMET_TIME,TIMET_TIME_MS,YYYYMMDD_TIME' >> ${TMPDIR}/datetime_excel.style
+ echo 'OFIELD LAT_DECIMAL,"","%.6f"' >> ${TMPDIR}/datetime_excel.style
+ echo 'OFIELD LON_DECIMAL,"","%.6f"' >> ${TMPDIR}/datetime_excel.style
+ echo 'OFIELD ISO_TIME, "", "%s"' >> ${TMPDIR}/datetime_excel.style
+ echo 'IFIELD LAT_DECIMAL,"","%.6f"' >> ${TMPDIR}/datetime_excel.style
+ echo 'IFIELD LON_DECIMAL,"","%.6f"' >> ${TMPDIR}/datetime_excel.style
+ echo 'IFIELD EXCEL_TIME, "", "%.12e"' >> ${TMPDIR}/datetime_excel.style
+ echo 'IFIELD IGNORE, "", "%I:%M:%S %p"' >> ${TMPDIR}/datetime_excel.style
+ echo 'IFIELD IGNORE, "", "%Y-%m-%d %H:%M:%S"' >> ${TMPDIR}/datetime_excel.style
+ echo 'IFIELD IGNORE, "", "%H:%M:%S"' >> ${TMPDIR}/datetime_excel.style
+ echo 'IFIELD IGNORE, "", "%I:%M:%S %p"' >> ${TMPDIR}/datetime_excel.style
+ echo 'IFIELD IGNORE, "", "%Y-%m-%d %H:%M:%S"' >> ${TMPDIR}/datetime_excel.style
+ echo 'IFIELD IGNORE, "", "%H:%M:%S"' >> ${TMPDIR}/datetime_excel.style
+ echo 'IFIELD IGNORE, "", "%s"' >> ${TMPDIR}/datetime_excel.style
+ echo 'IFIELD IGNORE, "", "%s"' >> ${TMPDIR}/datetime_excel.style
+ echo 'IFIELD IGNORE, "", "%lld"' >> ${TMPDIR}/datetime_excel.style
+ echo 'IFIELD IGNORE, "", "%lld"' >> ${TMPDIR}/datetime_excel.style
+ echo 'IFIELD IGNORE, "", "%lld"' >> ${TMPDIR}/datetime_excel.style
+ echo 'IFIELD IGNORE, "", "%ld"' >> ${TMPDIR}/datetime_excel.style
+
+ gpsbabel -i xcsv,style=${TMPDIR}/datetime_excel.style -f ${REFERENCE}/datetime~xcsv.xcsv -o xcsv,style=${TMPDIR}/datetime_excel.style -F ${TMPDIR}/datetime_excel.xcsv
+ compare ${REFERENCE}/datetime_read.xcsv ${TMPDIR}/datetime_excel.xcsv
+
+ echo 'FIELD_DELIMITER COMMA' > ${TMPDIR}/datetime_gmt.style
+ echo 'RECORD_DELIMITER NEWLINE' >> ${TMPDIR}/datetime_gmt.style
+ echo 'PROLOGUE LAT_DECIMAL,LON_DECIMAL,EXCEL_TIME,GMT_TIME-12HR,GMT_TIME-DATE-24HR,GMT_TIME-24HR,LOCAL_TIME-12HR,LOCAL_TIME-DATE-24HR,LOCAL_TIME-24HR,ISO_TIME,ISO_TIME_MS,NET_TIME,TIMET_TIME,TIMET_TIME_MS,YYYYMMDD_TIME' >> ${TMPDIR}/datetime_gmt.style
+ echo 'OFIELD LAT_DECIMAL,"","%.6f"' >> ${TMPDIR}/datetime_gmt.style
+ echo 'OFIELD LON_DECIMAL,"","%.6f"' >> ${TMPDIR}/datetime_gmt.style
+ echo 'OFIELD ISO_TIME, "", "%s"' >> ${TMPDIR}/datetime_gmt.style
+ echo 'IFIELD LAT_DECIMAL,"","%.6f"' >> ${TMPDIR}/datetime_gmt.style
+ echo 'IFIELD LON_DECIMAL,"","%.6f"' >> ${TMPDIR}/datetime_gmt.style
+ echo 'IFIELD IGNORE, "", "%.12e"' >> ${TMPDIR}/datetime_gmt.style
+ echo 'IFIELD IGNORE, "", "%I:%M:%S %p"' >> ${TMPDIR}/datetime_gmt.style
+ echo 'IFIELD GMT_TIME, "", "%Y-%m-%d %H:%M:%S"' >> ${TMPDIR}/datetime_gmt.style
+ echo 'IFIELD IGNORE, "", "%H:%M:%S"' >> ${TMPDIR}/datetime_gmt.style
+ echo 'IFIELD IGNORE, "", "%I:%M:%S %p"' >> ${TMPDIR}/datetime_gmt.style
+ echo 'IFIELD IGNORE, "", "%Y-%m-%d %H:%M:%S"' >> ${TMPDIR}/datetime_gmt.style
+ echo 'IFIELD IGNORE, "", "%H:%M:%S"' >> ${TMPDIR}/datetime_gmt.style
+ echo 'IFIELD IGNORE, "", "%s"' >> ${TMPDIR}/datetime_gmt.style
+ echo 'IFIELD IGNORE, "", "%s"' >> ${TMPDIR}/datetime_gmt.style
+ echo 'IFIELD IGNORE, "", "%lld"' >> ${TMPDIR}/datetime_gmt.style
+ echo 'IFIELD IGNORE, "", "%lld"' >> ${TMPDIR}/datetime_gmt.style
+ echo 'IFIELD IGNORE, "", "%lld"' >> ${TMPDIR}/datetime_gmt.style
+ echo 'IFIELD IGNORE, "", "%ld"' >> ${TMPDIR}/datetime_gmt.style
+
+ gpsbabel -i xcsv,style=${TMPDIR}/datetime_gmt.style -f ${REFERENCE}/datetime~xcsv.xcsv -o xcsv,style=${TMPDIR}/datetime_gmt.style -F ${TMPDIR}/datetime_gmt.xcsv
+ compare ${REFERENCE}/datetime_read.xcsv ${TMPDIR}/datetime_gmt.xcsv
+
+ echo 'FIELD_DELIMITER COMMA' > ${TMPDIR}/datetime_iso.style
+ echo 'RECORD_DELIMITER NEWLINE' >> ${TMPDIR}/datetime_iso.style
+ echo 'PROLOGUE LAT_DECIMAL,LON_DECIMAL,EXCEL_TIME,GMT_TIME-12HR,GMT_TIME-DATE-24HR,GMT_TIME-24HR,LOCAL_TIME-12HR,LOCAL_TIME-DATE-24HR,LOCAL_TIME-24HR,ISO_TIME,ISO_TIME_MS,NET_TIME,TIMET_TIME,TIMET_TIME_MS,YYYYMMDD_TIME' >> ${TMPDIR}/datetime_iso.style
+ echo 'OFIELD LAT_DECIMAL,"","%.6f"' >> ${TMPDIR}/datetime_iso.style
+ echo 'OFIELD LON_DECIMAL,"","%.6f"' >> ${TMPDIR}/datetime_iso.style
+ echo 'OFIELD ISO_TIME, "", "%s"' >> ${TMPDIR}/datetime_iso.style
+ echo 'IFIELD LAT_DECIMAL,"","%.6f"' >> ${TMPDIR}/datetime_iso.style
+ echo 'IFIELD LON_DECIMAL,"","%.6f"' >> ${TMPDIR}/datetime_iso.style
+ echo 'IFIELD IGNORE, "", "%.12e"' >> ${TMPDIR}/datetime_iso.style
+ echo 'IFIELD IGNORE, "", "%I:%M:%S %p"' >> ${TMPDIR}/datetime_iso.style
+ echo 'IFIELD IGNORE, "", "%Y-%m-%d %H:%M:%S"' >> ${TMPDIR}/datetime_iso.style
+ echo 'IFIELD IGNORE, "", "%H:%M:%S"' >> ${TMPDIR}/datetime_iso.style
+ echo 'IFIELD IGNORE, "", "%I:%M:%S %p"' >> ${TMPDIR}/datetime_iso.style
+ echo 'IFIELD IGNORE, "", "%Y-%m-%d %H:%M:%S"' >> ${TMPDIR}/datetime_iso.style
+ echo 'IFIELD IGNORE, "", "%H:%M:%S"' >> ${TMPDIR}/datetime_iso.style
+ echo 'IFIELD ISO_TIME, "", "%s"' >> ${TMPDIR}/datetime_iso.style
+ echo 'IFIELD IGNORE, "", "%s"' >> ${TMPDIR}/datetime_iso.style
+ echo 'IFIELD IGNORE, "", "%lld"' >> ${TMPDIR}/datetime_iso.style
+ echo 'IFIELD IGNORE, "", "%lld"' >> ${TMPDIR}/datetime_iso.style
+ echo 'IFIELD IGNORE, "", "%lld"' >> ${TMPDIR}/datetime_iso.style
+ echo 'IFIELD IGNORE, "", "%ld"' >> ${TMPDIR}/datetime_iso.style
+
+ gpsbabel -i xcsv,style=${TMPDIR}/datetime_iso.style -f ${REFERENCE}/datetime~xcsv.xcsv -o xcsv,style=${TMPDIR}/datetime_iso.style -F ${TMPDIR}/datetime_iso.xcsv
+ compare ${REFERENCE}/datetime_read.xcsv ${TMPDIR}/datetime_iso.xcsv
+
+ echo 'FIELD_DELIMITER COMMA' > ${TMPDIR}/datetime_isoms.style
+ echo 'RECORD_DELIMITER NEWLINE' >> ${TMPDIR}/datetime_isoms.style
+ echo 'PROLOGUE LAT_DECIMAL,LON_DECIMAL,EXCEL_TIME,GMT_TIME-12HR,GMT_TIME-DATE-24HR,GMT_TIME-24HR,LOCAL_TIME-12HR,LOCAL_TIME-DATE-24HR,LOCAL_TIME-24HR,ISO_TIME,ISO_TIME_MS,NET_TIME,TIMET_TIME,TIMET_TIME_MS,YYYYMMDD_TIME' >> ${TMPDIR}/datetime_isoms.style
+ echo 'OFIELD LAT_DECIMAL,"","%.6f"' >> ${TMPDIR}/datetime_isoms.style
+ echo 'OFIELD LON_DECIMAL,"","%.6f"' >> ${TMPDIR}/datetime_isoms.style
+ echo 'OFIELD ISO_TIME, "", "%s"' >> ${TMPDIR}/datetime_isoms.style
+ echo 'IFIELD LAT_DECIMAL,"","%.6f"' >> ${TMPDIR}/datetime_isoms.style
+ echo 'IFIELD LON_DECIMAL,"","%.6f"' >> ${TMPDIR}/datetime_isoms.style
+ echo 'IFIELD IGNORE, "", "%.12e"' >> ${TMPDIR}/datetime_isoms.style
+ echo 'IFIELD IGNORE, "", "%I:%M:%S %p"' >> ${TMPDIR}/datetime_isoms.style
+ echo 'IFIELD IGNORE, "", "%Y-%m-%d %H:%M:%S"' >> ${TMPDIR}/datetime_isoms.style
+ echo 'IFIELD IGNORE, "", "%H:%M:%S"' >> ${TMPDIR}/datetime_isoms.style
+ echo 'IFIELD IGNORE, "", "%I:%M:%S %p"' >> ${TMPDIR}/datetime_isoms.style
+ echo 'IFIELD IGNORE, "", "%Y-%m-%d %H:%M:%S"' >> ${TMPDIR}/datetime_isoms.style
+ echo 'IFIELD IGNORE, "", "%H:%M:%S"' >> ${TMPDIR}/datetime_isoms.style
+ echo 'IFIELD IGNORE, "", "%s"' >> ${TMPDIR}/datetime_isoms.style
+ echo 'IFIELD ISO_TIME_MS, "", "%s"' >> ${TMPDIR}/datetime_isoms.style
+ echo 'IFIELD IGNORE, "", "%lld"' >> ${TMPDIR}/datetime_isoms.style
+ echo 'IFIELD IGNORE, "", "%lld"' >> ${TMPDIR}/datetime_isoms.style
+ echo 'IFIELD IGNORE, "", "%lld"' >> ${TMPDIR}/datetime_isoms.style
+ echo 'IFIELD IGNORE, "", "%ld"' >> ${TMPDIR}/datetime_isoms.style
+
+ gpsbabel -i xcsv,style=${TMPDIR}/datetime_isoms.style -f ${REFERENCE}/datetime~xcsv.xcsv -o xcsv,style=${TMPDIR}/datetime_isoms.style -F ${TMPDIR}/datetime_isoms.xcsv
+ compare ${REFERENCE}/datetime_read.xcsv ${TMPDIR}/datetime_isoms.xcsv
+
+ echo 'FIELD_DELIMITER COMMA' > ${TMPDIR}/datetime_local.style
+ echo 'RECORD_DELIMITER NEWLINE' >> ${TMPDIR}/datetime_local.style
+ echo 'PROLOGUE LAT_DECIMAL,LON_DECIMAL,EXCEL_TIME,GMT_TIME-12HR,GMT_TIME-DATE-24HR,GMT_TIME-24HR,LOCAL_TIME-12HR,LOCAL_TIME-DATE-24HR,LOCAL_TIME-24HR,ISO_TIME,ISO_TIME_MS,NET_TIME,TIMET_TIME,TIMET_TIME_MS,YYYYMMDD_TIME' >> ${TMPDIR}/datetime_local.style
+ echo 'OFIELD LAT_DECIMAL,"","%.6f"' >> ${TMPDIR}/datetime_local.style
+ echo 'OFIELD LON_DECIMAL,"","%.6f"' >> ${TMPDIR}/datetime_local.style
+ echo 'OFIELD ISO_TIME, "", "%s"' >> ${TMPDIR}/datetime_local.style
+ echo 'IFIELD LAT_DECIMAL,"","%.6f"' >> ${TMPDIR}/datetime_local.style
+ echo 'IFIELD LON_DECIMAL,"","%.6f"' >> ${TMPDIR}/datetime_local.style
+ echo 'IFIELD IGNORE, "", "%.12e"' >> ${TMPDIR}/datetime_local.style
+ echo 'IFIELD IGNORE, "", "%I:%M:%S %p"' >> ${TMPDIR}/datetime_local.style
+ echo 'IFIELD IGNORE, "", "%Y-%m-%d %H:%M:%S"' >> ${TMPDIR}/datetime_local.style
+ echo 'IFIELD IGNORE, "", "%H:%M:%S"' >> ${TMPDIR}/datetime_local.style
+ echo 'IFIELD IGNORE, "", "%I:%M:%S %p"' >> ${TMPDIR}/datetime_local.style
+ echo 'IFIELD LOCAL_TIME, "", "%Y-%m-%d %H:%M:%S"' >> ${TMPDIR}/datetime_local.style
+ echo 'IFIELD IGNORE, "", "%H:%M:%S"' >> ${TMPDIR}/datetime_local.style
+ echo 'IFIELD IGNORE, "", "%s"' >> ${TMPDIR}/datetime_local.style
+ echo 'IFIELD IGNORE, "", "%s"' >> ${TMPDIR}/datetime_local.style
+ echo 'IFIELD IGNORE, "", "%lld"' >> ${TMPDIR}/datetime_local.style
+ echo 'IFIELD IGNORE, "", "%lld"' >> ${TMPDIR}/datetime_local.style
+ echo 'IFIELD IGNORE, "", "%lld"' >> ${TMPDIR}/datetime_local.style
+ echo 'IFIELD IGNORE, "", "%ld"' >> ${TMPDIR}/datetime_local.style
+
+ gpsbabel -i xcsv,style=${TMPDIR}/datetime_local.style -f ${REFERENCE}/datetime~xcsv.xcsv -o xcsv,style=${TMPDIR}/datetime_local.style -F ${TMPDIR}/datetime_local.xcsv
+ compare ${REFERENCE}/datetime_read.xcsv ${TMPDIR}/datetime_local.xcsv
+
+ echo 'FIELD_DELIMITER COMMA' > ${TMPDIR}/datetime_net.style
+ echo 'RECORD_DELIMITER NEWLINE' >> ${TMPDIR}/datetime_net.style
+ echo 'PROLOGUE LAT_DECIMAL,LON_DECIMAL,EXCEL_TIME,GMT_TIME-12HR,GMT_TIME-DATE-24HR,GMT_TIME-24HR,LOCAL_TIME-12HR,LOCAL_TIME-DATE-24HR,LOCAL_TIME-24HR,ISO_TIME,ISO_TIME_MS,NET_TIME,TIMET_TIME,TIMET_TIME_MS,YYYYMMDD_TIME' >> ${TMPDIR}/datetime_net.style
+ echo 'OFIELD LAT_DECIMAL,"","%.6f"' >> ${TMPDIR}/datetime_net.style
+ echo 'OFIELD LON_DECIMAL,"","%.6f"' >> ${TMPDIR}/datetime_net.style
+ echo 'OFIELD ISO_TIME, "", "%s"' >> ${TMPDIR}/datetime_net.style
+ echo 'IFIELD LAT_DECIMAL,"","%.6f"' >> ${TMPDIR}/datetime_net.style
+ echo 'IFIELD LON_DECIMAL,"","%.6f"' >> ${TMPDIR}/datetime_net.style
+ echo 'IFIELD IGNORE, "", "%.12e"' >> ${TMPDIR}/datetime_net.style
+ echo 'IFIELD IGNORE, "", "%I:%M:%S %p"' >> ${TMPDIR}/datetime_net.style
+ echo 'IFIELD IGNORE, "", "%Y-%m-%d %H:%M:%S"' >> ${TMPDIR}/datetime_net.style
+ echo 'IFIELD IGNORE, "", "%H:%M:%S"' >> ${TMPDIR}/datetime_net.style
+ echo 'IFIELD IGNORE, "", "%I:%M:%S %p"' >> ${TMPDIR}/datetime_net.style
+ echo 'IFIELD IGNORE, "", "%Y-%m-%d %H:%M:%S"' >> ${TMPDIR}/datetime_net.style
+ echo 'IFIELD IGNORE, "", "%H:%M:%S"' >> ${TMPDIR}/datetime_net.style
+ echo 'IFIELD IGNORE, "", "%s"' >> ${TMPDIR}/datetime_net.style
+ echo 'IFIELD IGNORE, "", "%s"' >> ${TMPDIR}/datetime_net.style
+ echo 'IFIELD NET_TIME, "", "%lld"' >> ${TMPDIR}/datetime_net.style
+ echo 'IFIELD IGNORE, "", "%lld"' >> ${TMPDIR}/datetime_net.style
+ echo 'IFIELD IGNORE, "", "%lld"' >> ${TMPDIR}/datetime_net.style
+ echo 'IFIELD IGNORE, "", "%ld"' >> ${TMPDIR}/datetime_net.style
+
+ gpsbabel -i xcsv,style=${TMPDIR}/datetime_net.style -f ${REFERENCE}/datetime~xcsv.xcsv -o xcsv,style=${TMPDIR}/datetime_net.style -F ${TMPDIR}/datetime_net.xcsv
+ compare ${REFERENCE}/datetime_read.xcsv ${TMPDIR}/datetime_net.xcsv
+
+ echo 'FIELD_DELIMITER COMMA' > ${TMPDIR}/datetime_timet.style
+ echo 'RECORD_DELIMITER NEWLINE' >> ${TMPDIR}/datetime_timet.style
+ echo 'PROLOGUE LAT_DECIMAL,LON_DECIMAL,EXCEL_TIME,GMT_TIME-12HR,GMT_TIME-DATE-24HR,GMT_TIME-24HR,LOCAL_TIME-12HR,LOCAL_TIME-DATE-24HR,LOCAL_TIME-24HR,ISO_TIME,ISO_TIME_MS,NET_TIME,TIMET_TIME,TIMET_TIME_MS,YYYYMMDD_TIME' >> ${TMPDIR}/datetime_timet.style
+ echo 'OFIELD LAT_DECIMAL,"","%.6f"' >> ${TMPDIR}/datetime_timet.style
+ echo 'OFIELD LON_DECIMAL,"","%.6f"' >> ${TMPDIR}/datetime_timet.style
+ echo 'OFIELD ISO_TIME, "", "%s"' >> ${TMPDIR}/datetime_timet.style
+ echo 'IFIELD LAT_DECIMAL,"","%.6f"' >> ${TMPDIR}/datetime_timet.style
+ echo 'IFIELD LON_DECIMAL,"","%.6f"' >> ${TMPDIR}/datetime_timet.style
+ echo 'IFIELD IGNORE, "", "%.12e"' >> ${TMPDIR}/datetime_timet.style
+ echo 'IFIELD IGNORE, "", "%I:%M:%S %p"' >> ${TMPDIR}/datetime_timet.style
+ echo 'IFIELD IGNORE, "", "%Y-%m-%d %H:%M:%S"' >> ${TMPDIR}/datetime_timet.style
+ echo 'IFIELD IGNORE, "", "%H:%M:%S"' >> ${TMPDIR}/datetime_timet.style
+ echo 'IFIELD IGNORE, "", "%I:%M:%S %p"' >> ${TMPDIR}/datetime_timet.style
+ echo 'IFIELD IGNORE, "", "%Y-%m-%d %H:%M:%S"' >> ${TMPDIR}/datetime_timet.style
+ echo 'IFIELD IGNORE, "", "%H:%M:%S"' >> ${TMPDIR}/datetime_timet.style
+ echo 'IFIELD IGNORE, "", "%s"' >> ${TMPDIR}/datetime_timet.style
+ echo 'IFIELD IGNORE, "", "%s"' >> ${TMPDIR}/datetime_timet.style
+ echo 'IFIELD IGNORE, "", "%lld"' >> ${TMPDIR}/datetime_timet.style
+ echo 'IFIELD TIMET_TIME, "", "%lld"' >> ${TMPDIR}/datetime_timet.style
+ echo 'IFIELD IGNORE, "", "%lld"' >> ${TMPDIR}/datetime_timet.style
+ echo 'IFIELD IGNORE, "", "%ld"' >> ${TMPDIR}/datetime_timet.style
+
+ gpsbabel -i xcsv,style=${TMPDIR}/datetime_timet.style -f ${REFERENCE}/datetime~xcsv.xcsv -o xcsv,style=${TMPDIR}/datetime_timet.style -F ${TMPDIR}/datetime_timet.xcsv
+ compare ${REFERENCE}/datetime_read.xcsv ${TMPDIR}/datetime_timet.xcsv
+
+ echo 'FIELD_DELIMITER COMMA' > ${TMPDIR}/datetime_timetms.style
+ echo 'RECORD_DELIMITER NEWLINE' >> ${TMPDIR}/datetime_timetms.style
+ echo 'PROLOGUE LAT_DECIMAL,LON_DECIMAL,EXCEL_TIME,GMT_TIME-12HR,GMT_TIME-DATE-24HR,GMT_TIME-24HR,LOCAL_TIME-12HR,LOCAL_TIME-DATE-24HR,LOCAL_TIME-24HR,ISO_TIME,ISO_TIME_MS,NET_TIME,TIMET_TIME,TIMET_TIME_MS,YYYYMMDD_TIME' >> ${TMPDIR}/datetime_timetms.style
+ echo 'OFIELD LAT_DECIMAL,"","%.6f"' >> ${TMPDIR}/datetime_timetms.style
+ echo 'OFIELD LON_DECIMAL,"","%.6f"' >> ${TMPDIR}/datetime_timetms.style
+ echo 'OFIELD ISO_TIME, "", "%s"' >> ${TMPDIR}/datetime_timetms.style
+ echo 'IFIELD LAT_DECIMAL,"","%.6f"' >> ${TMPDIR}/datetime_timetms.style
+ echo 'IFIELD LON_DECIMAL,"","%.6f"' >> ${TMPDIR}/datetime_timetms.style
+ echo 'IFIELD IGNORE, "", "%.12e"' >> ${TMPDIR}/datetime_timetms.style
+ echo 'IFIELD IGNORE, "", "%I:%M:%S %p"' >> ${TMPDIR}/datetime_timetms.style
+ echo 'IFIELD IGNORE, "", "%Y-%m-%d %H:%M:%S"' >> ${TMPDIR}/datetime_timetms.style
+ echo 'IFIELD IGNORE, "", "%H:%M:%S"' >> ${TMPDIR}/datetime_timetms.style
+ echo 'IFIELD IGNORE, "", "%I:%M:%S %p"' >> ${TMPDIR}/datetime_timetms.style
+ echo 'IFIELD IGNORE, "", "%Y-%m-%d %H:%M:%S"' >> ${TMPDIR}/datetime_timetms.style
+ echo 'IFIELD IGNORE, "", "%H:%M:%S"' >> ${TMPDIR}/datetime_timetms.style
+ echo 'IFIELD IGNORE, "", "%s"' >> ${TMPDIR}/datetime_timetms.style
+ echo 'IFIELD IGNORE, "", "%s"' >> ${TMPDIR}/datetime_timetms.style
+ echo 'IFIELD IGNORE, "", "%lld"' >> ${TMPDIR}/datetime_timetms.style
+ echo 'IFIELD IGNORE, "", "%lld"' >> ${TMPDIR}/datetime_timetms.style
+ echo 'IFIELD TIMET_TIME_MS, "", "%lld"' >> ${TMPDIR}/datetime_timetms.style
+ echo 'IFIELD IGNORE, "", "%ld"' >> ${TMPDIR}/datetime_timetms.style
+
+ gpsbabel -i xcsv,style=${TMPDIR}/datetime_timetms.style -f ${REFERENCE}/datetime~xcsv.xcsv -o xcsv,style=${TMPDIR}/datetime_timetms.style -F ${TMPDIR}/datetime_timetms.xcsv
+ compare ${REFERENCE}/datetime_read.xcsv ${TMPDIR}/datetime_timetms.xcsv
+
+ echo 'FIELD_DELIMITER COMMA' > ${TMPDIR}/datetime_hmsg.style
+ echo 'RECORD_DELIMITER NEWLINE' >> ${TMPDIR}/datetime_hmsg.style
+ echo 'PROLOGUE LAT_DECIMAL,LON_DECIMAL,EXCEL_TIME,GMT_TIME-12HR,GMT_TIME-DATE-24HR,GMT_TIME-24HR,LOCAL_TIME-12HR,LOCAL_TIME-DATE-24HR,LOCAL_TIME-24HR,ISO_TIME,ISO_TIME_MS,NET_TIME,TIMET_TIME,TIMET_TIME_MS,YYYYMMDD_TIME' >> ${TMPDIR}/datetime_hmsg.style
+ echo 'OFIELD LAT_DECIMAL,"","%.6f"' >> ${TMPDIR}/datetime_hmsg.style
+ echo 'OFIELD LON_DECIMAL,"","%.6f"' >> ${TMPDIR}/datetime_hmsg.style
+ echo 'OFIELD ISO_TIME, "", "%s"' >> ${TMPDIR}/datetime_hmsg.style
+ echo 'IFIELD LAT_DECIMAL,"","%.6f"' >> ${TMPDIR}/datetime_hmsg.style
+ echo 'IFIELD LON_DECIMAL,"","%.6f"' >> ${TMPDIR}/datetime_hmsg.style
+ echo 'IFIELD IGNORE, "", "%.12e"' >> ${TMPDIR}/datetime_hmsg.style
+ echo 'IFIELD GMT_TIME, "", "%I:%M:%S %p"' >> ${TMPDIR}/datetime_hmsg.style
+ echo 'IFIELD GMT_TIME, "", "%Y-%m-%d"' >> ${TMPDIR}/datetime_hmsg.style
+ echo 'IFIELD IGNORE, "", "%H:%M:%S"' >> ${TMPDIR}/datetime_hmsg.style
+ echo 'IFIELD IGNORE, "", "%I:%M:%S %p"' >> ${TMPDIR}/datetime_hmsg.style
+ echo 'IFIELD IGNORE, "", "%Y-%m-%d %H:%M:%S"' >> ${TMPDIR}/datetime_hmsg.style
+ echo 'IFIELD IGNORE, "", "%H:%M:%S"' >> ${TMPDIR}/datetime_hmsg.style
+ echo 'IFIELD IGNORE, "", "%s"' >> ${TMPDIR}/datetime_hmsg.style
+ echo 'IFIELD IGNORE, "", "%s"' >> ${TMPDIR}/datetime_hmsg.style
+ echo 'IFIELD IGNORE, "", "%lld"' >> ${TMPDIR}/datetime_hmsg.style
+ echo 'IFIELD IGNORE, "", "%lld"' >> ${TMPDIR}/datetime_hmsg.style
+ echo 'IFIELD IGNORE, "", "%lld"' >> ${TMPDIR}/datetime_hmsg.style
+ echo 'IFIELD IGNORE, "", "%ld"' >> ${TMPDIR}/datetime_hmsg.style
+
+ gpsbabel -i xcsv,style=${TMPDIR}/datetime_hmsg.style -f ${REFERENCE}/datetime~xcsv.xcsv -o xcsv,style=${TMPDIR}/datetime_hmsg.style -F ${TMPDIR}/datetime_hmsg.xcsv
+ compare ${REFERENCE}/datetime_read.xcsv ${TMPDIR}/datetime_hmsg.xcsv
+
+ echo 'FIELD_DELIMITER COMMA' > ${TMPDIR}/datetime_hmsg2.style
+ echo 'RECORD_DELIMITER NEWLINE' >> ${TMPDIR}/datetime_hmsg2.style
+ echo 'PROLOGUE LAT_DECIMAL,LON_DECIMAL,EXCEL_TIME,GMT_TIME-12HR,GMT_TIME-DATE-24HR,GMT_TIME-24HR,LOCAL_TIME-12HR,LOCAL_TIME-DATE-24HR,LOCAL_TIME-24HR,ISO_TIME,ISO_TIME_MS,NET_TIME,TIMET_TIME,TIMET_TIME_MS,YYYYMMDD_TIME' >> ${TMPDIR}/datetime_hmsg2.style
+ echo 'OFIELD LAT_DECIMAL,"","%.6f"' >> ${TMPDIR}/datetime_hmsg2.style
+ echo 'OFIELD LON_DECIMAL,"","%.6f"' >> ${TMPDIR}/datetime_hmsg2.style
+ echo 'OFIELD ISO_TIME, "", "%s"' >> ${TMPDIR}/datetime_hmsg2.style
+ echo 'IFIELD LAT_DECIMAL,"","%.6f"' >> ${TMPDIR}/datetime_hmsg2.style
+ echo 'IFIELD LON_DECIMAL,"","%.6f"' >> ${TMPDIR}/datetime_hmsg2.style
+ echo 'IFIELD IGNORE, "", "%.12e"' >> ${TMPDIR}/datetime_hmsg2.style
+ echo 'IFIELD IGNORE, "", "%I:%M:%S %p"' >> ${TMPDIR}/datetime_hmsg2.style
+ echo 'IFIELD GMT_TIME, "", "%Y-%m-%d"' >> ${TMPDIR}/datetime_hmsg2.style
+ echo 'IFIELD GMT_TIME, "", "%H:%M:%S"' >> ${TMPDIR}/datetime_hmsg2.style
+ echo 'IFIELD IGNORE, "", "%I:%M:%S %p"' >> ${TMPDIR}/datetime_hmsg2.style
+ echo 'IFIELD IGNORE, "", "%Y-%m-%d %H:%M:%S"' >> ${TMPDIR}/datetime_hmsg2.style
+ echo 'IFIELD IGNORE, "", "%H:%M:%S"' >> ${TMPDIR}/datetime_hmsg2.style
+ echo 'IFIELD IGNORE, "", "%s"' >> ${TMPDIR}/datetime_hmsg2.style
+ echo 'IFIELD IGNORE, "", "%s"' >> ${TMPDIR}/datetime_hmsg2.style
+ echo 'IFIELD IGNORE, "", "%lld"' >> ${TMPDIR}/datetime_hmsg2.style
+ echo 'IFIELD IGNORE, "", "%lld"' >> ${TMPDIR}/datetime_hmsg2.style
+ echo 'IFIELD IGNORE, "", "%lld"' >> ${TMPDIR}/datetime_hmsg2.style
+ echo 'IFIELD IGNORE, "", "%ld"' >> ${TMPDIR}/datetime_hmsg2.style
+
+ gpsbabel -i xcsv,style=${TMPDIR}/datetime_hmsg2.style -f ${REFERENCE}/datetime~xcsv.xcsv -o xcsv,style=${TMPDIR}/datetime_hmsg2.style -F ${TMPDIR}/datetime_hmsg2.xcsv
+ compare ${REFERENCE}/datetime_read.xcsv ${TMPDIR}/datetime_hmsg2.xcsv
+
+ echo 'FIELD_DELIMITER COMMA' > ${TMPDIR}/datetime_hmsl.style
+ echo 'RECORD_DELIMITER NEWLINE' >> ${TMPDIR}/datetime_hmsl.style
+ echo 'PROLOGUE LAT_DECIMAL,LON_DECIMAL,EXCEL_TIME,GMT_TIME-12HR,GMT_TIME-DATE-24HR,GMT_TIME-24HR,LOCAL_TIME-12HR,LOCAL_TIME-DATE-24HR,LOCAL_TIME-24HR,ISO_TIME,ISO_TIME_MS,NET_TIME,TIMET_TIME,TIMET_TIME_MS,YYYYMMDD_TIME' >> ${TMPDIR}/datetime_hmsl.style
+ echo 'OFIELD LAT_DECIMAL,"","%.6f"' >> ${TMPDIR}/datetime_hmsl.style
+ echo 'OFIELD LON_DECIMAL,"","%.6f"' >> ${TMPDIR}/datetime_hmsl.style
+ echo 'OFIELD ISO_TIME, "", "%s"' >> ${TMPDIR}/datetime_hmsl.style
+ echo 'IFIELD LAT_DECIMAL,"","%.6f"' >> ${TMPDIR}/datetime_hmsl.style
+ echo 'IFIELD LON_DECIMAL,"","%.6f"' >> ${TMPDIR}/datetime_hmsl.style
+ echo 'IFIELD IGNORE, "", "%.12e"' >> ${TMPDIR}/datetime_hmsl.style
+ echo 'IFIELD IGNORE, "", "%I:%M:%S %p"' >> ${TMPDIR}/datetime_hmsl.style
+ echo 'IFIELD IGNORE, "", "%Y-%m-%d %H:%M:%S"' >> ${TMPDIR}/datetime_hmsl.style
+ echo 'IFIELD IGNORE, "", "%H:%M:%S"' >> ${TMPDIR}/datetime_hmsl.style
+ echo 'IFIELD LOCAL_TIME, "", "%I:%M:%S %p"' >> ${TMPDIR}/datetime_hmsl.style
+ echo 'IFIELD LOCAL_TIME, "", "%Y-%m-%d"' >> ${TMPDIR}/datetime_hmsl.style
+ echo 'IFIELD IGNORE, "", "%H:%M:%S"' >> ${TMPDIR}/datetime_hmsl.style
+ echo 'IFIELD IGNORE, "", "%s"' >> ${TMPDIR}/datetime_hmsl.style
+ echo 'IFIELD IGNORE, "", "%s"' >> ${TMPDIR}/datetime_hmsl.style
+ echo 'IFIELD IGNORE, "", "%lld"' >> ${TMPDIR}/datetime_hmsl.style
+ echo 'IFIELD IGNORE, "", "%lld"' >> ${TMPDIR}/datetime_hmsl.style
+ echo 'IFIELD IGNORE, "", "%lld"' >> ${TMPDIR}/datetime_hmsl.style
+ echo 'IFIELD IGNORE, "", "%ld"' >> ${TMPDIR}/datetime_hmsl.style
+
+ gpsbabel -i xcsv,style=${TMPDIR}/datetime_hmsl.style -f ${REFERENCE}/datetime~xcsv.xcsv -o xcsv,style=${TMPDIR}/datetime_hmsl.style -F ${TMPDIR}/datetime_hmsl.xcsv
+ compare ${REFERENCE}/datetime_read.xcsv ${TMPDIR}/datetime_hmsl.xcsv
+
+ echo 'FIELD_DELIMITER COMMA' > ${TMPDIR}/datetime_hmsl2.style
+ echo 'RECORD_DELIMITER NEWLINE' >> ${TMPDIR}/datetime_hmsl2.style
+ echo 'PROLOGUE LAT_DECIMAL,LON_DECIMAL,EXCEL_TIME,GMT_TIME-12HR,GMT_TIME-DATE-24HR,GMT_TIME-24HR,LOCAL_TIME-12HR,LOCAL_TIME-DATE-24HR,LOCAL_TIME-24HR,ISO_TIME,ISO_TIME_MS,NET_TIME,TIMET_TIME,TIMET_TIME_MS,YYYYMMDD_TIME' >> ${TMPDIR}/datetime_hmsl2.style
+ echo 'OFIELD LAT_DECIMAL,"","%.6f"' >> ${TMPDIR}/datetime_hmsl2.style
+ echo 'OFIELD LON_DECIMAL,"","%.6f"' >> ${TMPDIR}/datetime_hmsl2.style
+ echo 'OFIELD ISO_TIME, "", "%s"' >> ${TMPDIR}/datetime_hmsl2.style
+ echo 'IFIELD LAT_DECIMAL,"","%.6f"' >> ${TMPDIR}/datetime_hmsl2.style
+ echo 'IFIELD LON_DECIMAL,"","%.6f"' >> ${TMPDIR}/datetime_hmsl2.style
+ echo 'IFIELD IGNORE, "", "%.12e"' >> ${TMPDIR}/datetime_hmsl2.style
+ echo 'IFIELD IGNORE, "", "%I:%M:%S %p"' >> ${TMPDIR}/datetime_hmsl2.style
+ echo 'IFIELD IGNORE, "", "%Y-%m-%d %H:%M:%S"' >> ${TMPDIR}/datetime_hmsl2.style
+ echo 'IFIELD IGNORE, "", "%H:%M:%S"' >> ${TMPDIR}/datetime_hmsl2.style
+ echo 'IFIELD IGNORE, "", "%I:%M:%S %p"' >> ${TMPDIR}/datetime_hmsl2.style
+ echo 'IFIELD LOCAL_TIME, "", "%Y-%m-%d"' >> ${TMPDIR}/datetime_hmsl2.style
+ echo 'IFIELD LOCAL_TIME, "", "%H:%M:%S"' >> ${TMPDIR}/datetime_hmsl2.style
+ echo 'IFIELD IGNORE, "", "%s"' >> ${TMPDIR}/datetime_hmsl2.style
+ echo 'IFIELD IGNORE, "", "%s"' >> ${TMPDIR}/datetime_hmsl2.style
+ echo 'IFIELD IGNORE, "", "%lld"' >> ${TMPDIR}/datetime_hmsl2.style
+ echo 'IFIELD IGNORE, "", "%lld"' >> ${TMPDIR}/datetime_hmsl2.style
+ echo 'IFIELD IGNORE, "", "%lld"' >> ${TMPDIR}/datetime_hmsl2.style
+ echo 'IFIELD IGNORE, "", "%ld"' >> ${TMPDIR}/datetime_hmsl2.style
+
+ gpsbabel -i xcsv,style=${TMPDIR}/datetime_hmsl2.style -f ${REFERENCE}/datetime~xcsv.xcsv -o xcsv,style=${TMPDIR}/datetime_hmsl2.style -F ${TMPDIR}/datetime_hmsl2.xcsv
+ compare ${REFERENCE}/datetime_read.xcsv ${TMPDIR}/datetime_hmsl2.xcsv
+
+ unset -v TZ
+fi
#include <cmath> // for fabs, lround
#include <cstdio> // for NULL, sscanf
-#include <cstring> // for strchr, strncpy
-#include <ctime> // for gmtime
+#include <ctime> // for tm
#include <QByteArray> // for QByteArray
#include <QChar> // for QChar
return res;
}
-time_t
+QDate
UnicsvFormat::unicsv_parse_date(const char* str, int* consumed)
{
int p1, p2, p3;
if (ct != 5) {
if (consumed) { /* don't stop here; it's only sniffing */
*consumed = 0; /* for a possible date */
- return 0;
+ return {};
}
- fatal(FatalMsg() << MYNAME << ": Could not parse date string (" << str << ").\n");
+ fatal(FatalMsg() << MYNAME << ": Could not parse date string (" << str << ").");
}
if ((p1 > 99) || (sep[0] == '-')) { /* Y-M-D (iso like) */
if ((tm.tm_mon > 12) || (tm.tm_mon < 1) || (tm.tm_mday > 31) || (tm.tm_mday < 1)) {
if (consumed) {
*consumed = 0;
- return 0; /* don't stop here */
+ return {}; /* don't stop here */
}
- fatal(FatalMsg() << MYNAME << ": Could not parse date string (" << str << ").\n");
+ fatal(FatalMsg() << MYNAME << ": Could not parse date string (" << str << ").");
}
- tm.tm_year -= 1900;
- tm.tm_mon -= 1;
-
- return mkgmtime(&tm);
+ QDate result{tm.tm_year, tm.tm_mon, tm.tm_mday};
+ if (!result.isValid()) {
+ fatal(FatalMsg() << MYNAME << ": Invalid date parsed from string (" << str << ").");
+ }
+ return result;
}
-time_t
-UnicsvFormat::unicsv_parse_time(const char* str, int* usec, time_t* date)
+QTime
+UnicsvFormat::unicsv_parse_time(const char* str, QDate& date)
{
- int hour, min, sec;
+ int hour;
+ int min;
+ int sec;
+ int msec;
int consumed = 0;
- double us;
- char sep[2];
+ double frac_sec;
/* If we have something we're pretty sure is a date, parse that
* first, skip over it, and pass that back to the caller)
*/
- time_t ldate = unicsv_parse_date(str, &consumed);
- if (consumed && ldate) {
+ QDate ldate = unicsv_parse_date(str, &consumed);
+ if (consumed && ldate.isValid()) {
str += consumed;
- if (date) {
- *date = ldate;
- }
+ date = ldate;
}
- int ct = sscanf(str, "%d%1[.://]%d%1[.://]%d%lf", &hour, sep, &min, sep, &sec, &us);
- if (ct < 5) {
- fatal(MYNAME ": Could not parse time string (%s).\n", str);
+ int ct = sscanf(str, "%d%*1[.://]%d%*1[.://]%d%lf", &hour, &min, &sec, &frac_sec);
+ if (ct < 3) {
+ fatal(FatalMsg() << MYNAME << ": Could not parse time string (" << str << ").");
}
- if (ct == 6) {
- *usec = lround((us * 1000000));
- if (*usec > 999999) {
- *usec = 0;
- sec++;
- }
+ if (ct >= 4) {
+ // Don't round up and ripple through seconds, minutes, hours.
+ // 23:59:59.9999999 -> 24:00:00.000 which is an invalid QTime.
+ msec = frac_sec * 1000.0;
} else {
- *usec = 0;
+ msec = 0;
}
- return ((hour * SECONDS_PER_HOUR) + (min * 60) + sec);
+ QTime result{hour, min, sec, msec};
+ if (!result.isValid()) {
+ fatal(FatalMsg() << MYNAME << ": Invalid time parsed from string (" << str << ").");
+ }
+ return result;
}
-time_t
-UnicsvFormat::unicsv_parse_time(const QString& str, int* msec, time_t* date)
+QTime
+UnicsvFormat::unicsv_parse_time(const QString& str, QDate& date)
{
- return unicsv_parse_time(CSTR(str), msec, date);
+ return unicsv_parse_time(CSTR(str), date);
}
Geocache::status_t
}
QDateTime
-UnicsvFormat::unicsv_adjust_time(const time_t time, const time_t* date) const
+UnicsvFormat::unicsv_adjust_time(const QDate date, const QTime time, bool is_localtime) const
{
- time_t res = time;
- if (date) {
- res += *date;
- }
- if (opt_utc) {
- res += xstrtoi(opt_utc, nullptr, 10) * SECONDS_PER_HOUR;
- } else {
- std::tm tm = *gmtime(&res);
- res = mklocaltime(&tm);
- }
- return QDateTime::fromSecsSinceEpoch(res, Qt::UTC);
+ return make_datetime(date, time, is_localtime, opt_utc != nullptr, utc_offset);
}
bool
} else {
unicsv_fieldsep = nullptr;
}
+
+ utc_offset = (opt_utc == nullptr)? 0 : xstrtoi(opt_utc, nullptr, 10) * SECONDS_PER_HOUR;
}
void
double swiss_easting = kUnicsvUnknown;
double swiss_northing = kUnicsvUnknown;
int checked = 0;
- time_t date = -1;
- time_t time = -1;
- int usec = -1;
- char is_localtime = 0;
+ QDate local_date;
+ QTime local_time;
+ QDate utc_date;
+ QTime utc_time;
+ bool need_datetime = true;
garmin_fs_t* gmsd;
double d;
std::tm ymd{};
break;
case fld_utc_date:
- if ((is_localtime < 2) && (date < 0)) {
- date = unicsv_parse_date(CSTR(value), nullptr);
- is_localtime = 0;
+ if (need_datetime && !utc_date.isValid()) {
+ utc_date = unicsv_parse_date(CSTR(value), nullptr);
}
break;
case fld_utc_time:
- if ((is_localtime < 2) && (time < 0)) {
- time = unicsv_parse_time(value, &usec, &date);
- is_localtime = 0;
+ if (need_datetime && !utc_time.isValid()) {
+ utc_time = unicsv_parse_time(value, utc_date);
}
break;
break;
case fld_iso_time:
- is_localtime = 2; /* fix result */
- wpt->SetCreationTime(xml_parse_time(value));
+ need_datetime = false; /* fix result */
+ wpt->SetCreationTime(QDateTime::fromString(value, Qt::ISODateWithMs));
break;
case fld_time:
- if ((is_localtime < 2) && (time < 0)) {
- time = unicsv_parse_time(value, &usec, &date);
- is_localtime = 1;
+ if (need_datetime && !local_time.isValid()) {
+ local_time = unicsv_parse_time(value, local_date);
}
break;
case fld_date:
- if ((is_localtime < 2) && (date < 0)) {
- date = unicsv_parse_date(CSTR(value), nullptr);
- is_localtime = 1;
+ if (need_datetime && !local_date.isValid()) {
+ local_date = unicsv_parse_date(CSTR(value), nullptr);
}
break;
break;
case fld_datetime:
- if ((is_localtime < 2) && (date < 0) && (time < 0)) {
- time = unicsv_parse_time(value, &usec, &date);
- is_localtime = 1;
+ if (need_datetime && !local_date.isValid() && !local_time.isValid()) {
+ local_time = unicsv_parse_time(value, local_date);
}
break;
gc_data->is_available = unicsv_parse_status(value);
break;
case fld_gc_exported: {
- time_t etime, edate;
- int eusec;
- etime = unicsv_parse_time(value, &eusec, &edate);
- if (edate || etime) {
- gc_data->exported = unicsv_adjust_time(etime, &edate);
+ QTime etime;
+ QDate edate;
+ etime = unicsv_parse_time(value, edate);
+ if (edate.isValid() || etime.isValid()) {
+ gc_data->exported = unicsv_adjust_time(edate, etime, true);
}
}
break;
case fld_gc_last_found: {
- time_t ftime, fdate;
- int fusec;
- ftime = unicsv_parse_time(value, &fusec, &fdate);
- if (fdate || ftime) {
- gc_data->last_found = unicsv_adjust_time(ftime, &fdate);
+ QTime ftime;
+ QDate fdate;
+ ftime = unicsv_parse_time(value, fdate);
+ if (fdate.isValid() || ftime.isValid()) {
+ gc_data->last_found = unicsv_adjust_time(fdate, ftime, true);
}
}
break;
return;
}
- if (is_localtime < 2) { /* not fixed */
- if ((time >= 0) && (date >= 0)) {
- time_t t = date + time;
-
- if (is_localtime) {
- std::tm tm = *gmtime(&t);
- if (opt_utc) {
- wpt->SetCreationTime(mkgmtime(&tm));
- } else {
- wpt->SetCreationTime(mklocaltime(&tm));
- }
- } else {
- wpt->SetCreationTime(t);
- }
- } else if (time >= 0) {
- wpt->SetCreationTime(time);
- } else if (date >= 0) {
- wpt->SetCreationTime(date);
+ if (need_datetime) { /* not fixed */
+ if (utc_date.isValid() && utc_time.isValid()) {
+ wpt->SetCreationTime(unicsv_adjust_time(utc_date, utc_time, false));
+ } else if (local_date.isValid() && local_time.isValid()) {
+ wpt->SetCreationTime(unicsv_adjust_time(local_date, local_time, true));
+ } else if (utc_date.isValid()) {
+ wpt->SetCreationTime(unicsv_adjust_time(utc_date, utc_time, false));
+ } else if (local_date.isValid()) {
+ wpt->SetCreationTime(unicsv_adjust_time(local_date, local_time, true));
+ } else if (utc_time.isValid()) {
+ wpt->SetCreationTime(unicsv_adjust_time(utc_date, utc_time, false));
+ } else if (local_time.isValid()) {
+ wpt->SetCreationTime(unicsv_adjust_time(local_date, local_time, true));
} else if (ymd.tm_year || ymd.tm_mon || ymd.tm_mday) {
if (ymd.tm_year < 100) {
if (ymd.tm_year <= 70) {
ymd.tm_year += 1900;
}
}
- ymd.tm_year -= 1900;
if (ymd.tm_mon == 0) {
ymd.tm_mon = 1;
ymd.tm_mday = 1;
}
- ymd.tm_mon--;
- if (opt_utc) {
- wpt->SetCreationTime(mkgmtime(&ymd));
- } else {
- wpt->SetCreationTime(mklocaltime(&ymd));
- }
+ wpt->SetCreationTime(unicsv_adjust_time(
+ QDate(ymd.tm_year, ymd.tm_mon, ymd.tm_mday),
+ QTime(ymd.tm_hour, ymd.tm_min, ymd.tm_sec),
+ true));
} else if (ymd.tm_hour || ymd.tm_min || ymd.tm_sec) {
- if (opt_utc) {
- wpt->SetCreationTime(mkgmtime(&ymd));
- } else {
- wpt->SetCreationTime(mklocaltime(&ymd));
- }
- }
-
- if (usec >= 0) {
- wpt->creation_time = wpt->creation_time.addMSecs(MICRO_TO_MILLI(usec));
+ wpt->SetCreationTime(unicsv_adjust_time(
+ QDate(),
+ QTime(ymd.tm_hour, ymd.tm_min, ymd.tm_sec),
+ true));
}
- if (opt_utc) {
- wpt->creation_time = wpt->creation_time.addSecs(xstrtoi(opt_utc, nullptr, 10) * SECONDS_PER_HOUR);
- }
}
/* utm/bng/swiss can be optional */
}
void
-UnicsvFormat::unicsv_print_data_time(const QDateTime& idt) const
+UnicsvFormat::unicsv_print_date_time(const QDateTime& idt) const
{
if (!idt.isValid()) {
return;
}
- QDateTime dt = idt;
- if (opt_utc) {
- //time += xstrtoi(opt_utc, nullptr, 10) * SECONDS_PER_HOUR;
- dt = dt.addSecs(xstrtoi(opt_utc, nullptr, 10) * SECONDS_PER_HOUR);
- dt = dt.toUTC();
+ QDateTime dt;
+ if (opt_utc != nullptr) {
+ dt = idt.toOffsetFromUtc(utc_offset);
+ } else {
+ dt = idt.toLocalTime();
}
unicsv_print_str(dt.toString(u"yyyy/MM/dd hh:mm:ss"));
}
if (wpt->creation_time.isValid()) {
unicsv_outp_flags[fld_time] = true;
- if (wpt->creation_time.toTime_t() >= SECONDS_PER_DAY) {
+ if (wpt->creation_time.toTime_t() >= 2 * SECONDS_PER_DAY) {
unicsv_outp_flags[fld_date] = true;
}
}
}
}
if (unicsv_outp_flags[fld_date]) {
- if (wpt->creation_time.toTime_t() >= SECONDS_PER_DAY) {
+ if (wpt->creation_time.toTime_t() >= 2 * SECONDS_PER_DAY) {
QDateTime dt;
- if (opt_utc) {
- dt = wpt->GetCreationTime().toUTC();
- // We might wrap to a different day by overriding the TZ offset.
- dt = dt.addSecs(xstrtoi(opt_utc, nullptr, 10) * SECONDS_PER_HOUR);
+ if (opt_utc != nullptr) {
+ dt = wpt->GetCreationTime().toOffsetFromUtc(utc_offset);
} else {
dt = wpt->GetCreationTime().toLocalTime();
}
}
if (unicsv_outp_flags[fld_time]) {
if (wpt->creation_time.isValid()) {
- QTime t;
- if (opt_utc) {
- t = wpt->GetCreationTime().toUTC().time();
- t = t.addSecs(xstrtoi(opt_utc, nullptr, 10) * SECONDS_PER_HOUR);
+ QDateTime dt;
+ if (opt_utc != nullptr) {
+ dt = wpt->GetCreationTime().toOffsetFromUtc(utc_offset);
} else {
- t = wpt->GetCreationTime().toLocalTime().time();
+ dt = wpt->GetCreationTime().toLocalTime();
}
QString out;
- if (t.msec() > 0) {
- out = t.toString(u"hh:mm:ss.zzz");
+ if (dt.time().msec() > 0) {
+ out = dt.toString(u"hh:mm:ss.zzz");
} else {
- out = t.toString(u"hh:mm:ss");
+ out = dt.toString(u"hh:mm:ss");
}
*fout << unicsv_fieldsep << out;
} else {
}
if (unicsv_outp_flags[fld_gc_exported]) {
if (gc_data) {
- unicsv_print_data_time(gc_data->exported);
+ unicsv_print_date_time(gc_data->exported);
} else {
*fout << unicsv_fieldsep;
}
}
if (unicsv_outp_flags[fld_gc_last_found]) {
if (gc_data) {
- unicsv_print_data_time(gc_data->last_found);
+ unicsv_print_date_time(gc_data->last_found);
} else {
*fout << unicsv_fieldsep;
}
}
llprec = xstrtoi(opt_prec, nullptr, 10);
+ utc_offset = (opt_utc == nullptr)? 0 : xstrtoi(opt_utc, nullptr, 10) * SECONDS_PER_HOUR;
}
void
#include <bitset> // for bitset
#include <cstdint> // for uint32_t
-#include <ctime> // for gmtime
+#include <QDate> // for QDate
#include <QDateTime> // for QDateTime
#include <QString> // for QString
+#include <QTime> // for QTime
#include <QVector> // for QVector
#include "defs.h"
/* Member Functions */
static long long int unicsv_parse_gc_code(const QString& str);
- static time_t unicsv_parse_date(const char* str, int* consumed);
- static time_t unicsv_parse_time(const char* str, int* usec, time_t* date);
- static time_t unicsv_parse_time(const QString& str, int* msec, time_t* date);
+ static QDate unicsv_parse_date(const char* str, int* consumed);
+ static QTime unicsv_parse_time(const char* str, QDate& date);
+ static QTime unicsv_parse_time(const QString& str, QDate& date);
static Geocache::status_t unicsv_parse_status(const QString& str);
- QDateTime unicsv_adjust_time(time_t time, const time_t* date) const;
+ QDateTime unicsv_adjust_time(const QDate date, const QTime time, bool is_localtime) const;
static bool unicsv_compare_fields(const QString& s, const field_t* f);
void unicsv_fondle_header(QString header);
void unicsv_parse_one_line(const QString& ibuf);
void unicsv_fatal_outside(const Waypoint* wpt) const;
void unicsv_print_str(const QString& s) const;
- void unicsv_print_data_time(const QDateTime& idt) const;
+ void unicsv_print_date_time(const QDateTime& idt) const;
void unicsv_waypt_enum_cb(const Waypoint* wpt);
void unicsv_waypt_disp_cb(const Waypoint* wpt);
static void unicsv_check_modes(bool test);
int unicsv_waypt_ct{};
char unicsv_detect{};
int llprec{};
+ int utc_offset{};
QVector<arglist_t> unicsv_args = {
{
},
{
"utc", &opt_utc, "Write timestamps with offset x to UTC time",
- nullptr, ARGTYPE_INT, "-23", "+23", nullptr
+ nullptr, ARGTYPE_INT, "-14", "+14", nullptr
},
{
"format", &opt_format, "Write name(s) of format(s) from input session(s)",
#include <cmath> // for fabs, floor
#include <cstdarg> // for va_list, va_end, va_start, va_copy
#include <cstdio> // for size_t, vsnprintf, FILE, fopen, printf, sprintf, stderr, stdin, stdout
-#include <cstdint> // for uint32_t
#include <cstdlib> // for abs, calloc, free, malloc, realloc
#include <cstring> // for strlen, strcat, strstr, memcpy, strcmp, strcpy, strdup, strchr, strerror
-#include <ctime> // for mktime, localtime
#include <QByteArray> // for QByteArray
#include <QChar> // for QChar, operator<=, operator>=
p[3] = value >> 24;
}
-/*
- mkgmtime -- convert tm struct in UTC to time_t
-
- works just like mktime but without all the mucking
- around with timezones and daylight savings
-
- Borrowed from lynx GPL source code
- http://lynx.isc.org/release/lynx2-8-5/src/mktime.c
-
- Written by Philippe De Muyter <phdm@macqel.be>.
-*/
-
-time_t
-mkgmtime(std::tm* time)
+QDateTime
+make_datetime(QDate date, QTime time, bool is_localtime, bool force_utc, int utc_offset)
{
- static const int m_to_d[12] =
- {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
-
- short month = time->tm_mon;
- short year = time->tm_year + month / 12 + 1900;
- month %= 12;
- if (month < 0) {
- year -= 1;
- month += 12;
- }
- time_t result = (year - 1970) * 365 + m_to_d[month];
- if (month <= 1) {
- year -= 1;
+ QDateTime result;
+ Qt::TimeSpec timespec;
+ int offset = 0;
+
+ if (is_localtime) {
+ if (force_utc) { // override with passed option value
+ if (utc_offset == 0) {
+ // Qt 6.5.0 QDate::startOfDay(Qt::OffsetFromUTC, 0) returns an invalid QDateTime.
+ timespec = Qt::UTC;
+ } else {
+ timespec = Qt::OffsetFromUTC;
+ // Avoid Qt 6.5.0 warnings with non-zero offsets when not using Qt::OffsetFromUTC.
+ offset = utc_offset;
+ }
+ } else {
+ timespec = Qt::LocalTime;
+ }
+ } else {
+ timespec = Qt::UTC;
}
- result += (year - 1968) / 4;
- result -= (year - 1900) / 100;
- result += (year - 1600) / 400;
- result += time->tm_mday;
- result -= 1;
- result *= 24;
- result += time->tm_hour;
- result *= 60;
- result += time->tm_min;
- result *= 60;
- result += time->tm_sec;
- return (result);
-}
-/*
- * mklocaltime: same as mktime, but try to recover the "Summer time flag",
- * which is evaluated by mktime
- */
-time_t
-mklocaltime(std::tm* time)
-{
- time_t result;
- std::tm check = *time;
-
- check.tm_isdst = 0;
- result = mktime(&check);
- check = *localtime(&result);
- if (check.tm_isdst == 1) { /* DST is in effect */
- check = *time;
- check.tm_isdst = 1;
- result = mktime(&check);
+ if (date.isValid() && time.isValid()) {
+ result = QDateTime(date, time, timespec, offset);
+ } else if (time.isValid()) {
+ // TODO: Wouldn't it be better to return an invalid QDateTime
+ // that contained an invalid QDate, a valid QTime and a valid
+ // Qt::TimeSpec?
+ result = QDateTime(QDate(1970, 1, 1), time, timespec, offset);
+ } else if (date.isValid()) {
+ // no time, use start of day in the given Qt::TimeSpec.
+#if (QT_VERSION < QT_VERSION_CHECK(5, 14, 0))
+ result = QDateTime(date, QTime(0,0), timespec, offset);
+#else
+ result = date.startOfDay(timespec, offset);
+#endif
}
+
return result;
}
return epoch.addMSecs(millisecs);
}
+long long qdatetime_to_dotnet_time(const QDateTime& dt)
+{
+ QDateTime epoch = QDateTime(QDate(1, 1, 1), QTime(0, 0, 0), Qt::UTC);
+ qint64 millisecs = epoch.msecsTo(dt);
+ return millisecs * 10000;
+}
+
double
endian_read_double(const void* ptr, int read_le)
{
#include <cctype> // for isdigit, tolower
#include <cmath> // for fabs, pow
#include <cstdio> // for snprintf, sscanf
+#include <cstdint> // for uint32_t
#include <cstdlib> // for strtod
#include <cstring> // for strlen, strncmp, strcmp
#include <ctime> // for gmtime, localtime, time_t, mktime, strftime
{ "GPS_SAT", XT_GPS_SAT },
{ "GPS_VDOP", XT_GPS_VDOP },
{ "HEART_RATE", XT_HEART_RATE },
- { "HMSG_TIME", XT_HMSG_TIME },
- { "HMSL_TIME", XT_HMSL_TIME },
{ "ICON_DESCR", XT_ICON_DESCR },
{ "IGNORE", XT_IGNORE },
{ "INDEX", XT_INDEX },
style->ofields.append(fmp);
}
-QDateTime
+QDate
XcsvFormat::yyyymmdd_to_time(const QString& s)
{
- QDate d = QDate::fromString(s, "yyyyMMdd");
-#if (QT_VERSION < QT_VERSION_CHECK(5, 14, 0))
- return QDateTime(d);
-#else
- return d.startOfDay();
-#endif
+ return QDate::fromString(s, "yyyyMMdd");
}
+QDateTime
+XcsvFormat::xcsv_adjust_time(const QDate date, const QTime time, bool is_localtime) const
+{
+ return make_datetime(date, time, is_localtime, opt_utc != nullptr, utc_offset);
+}
/*
* sscanftime - Parse a date buffer using strftime format
*/
-time_t
-XcsvFormat::sscanftime(const char* s, const char* format, bool gmt)
+void
+XcsvFormat::sscanftime(const char* s, const char* format, QDate& date, QTime& time)
{
std::tm stm{};
+ stm.tm_sec = -1;
+ stm.tm_min = -1;
+ stm.tm_hour = -1;
+ stm.tm_mday = -1;
+ stm.tm_mon = -1;
+ stm.tm_year = -1;
+ stm.tm_wday = -1;
+ stm.tm_yday = -1;
+ stm.tm_isdst = -1;
if (strptime(s, format, &stm)) {
- if ((stm.tm_mday == 0) && (stm.tm_mon == 0) && (stm.tm_year == 0)) {
- stm.tm_mday = 1;
- stm.tm_mon = 0;
- stm.tm_year = 70;
- }
- stm.tm_isdst = -1;
- if (gmt) {
- return mkgmtime(&stm);
- } else {
- return mktime(&stm);
+
+ std::optional<QTime> time_result;
+ bool bad_time_parse = false;
+ if (stm.tm_hour >= 0 && stm.tm_min >= 0 && stm.tm_sec >= 0) {
+ time_result = QTime(stm.tm_hour, stm.tm_min, stm.tm_sec);
+ } else if (stm.tm_hour >= 0 && stm.tm_min >= 0) {
+ time_result = QTime(stm.tm_hour, stm.tm_min, 0);
+ } else if (stm.tm_hour >= 0) {
+ time_result = QTime(stm.tm_hour, 0, 0);
+ } else if (!(stm.tm_hour == -1 && stm.tm_min == -1 && stm.tm_sec == -1)) {
+ bad_time_parse = true;
}
- }
- // Don't fuss for empty strings.
- if (*s) {
- warning("date parse of string '%s' with format '%s' failed.\n",
+ if ((time_result.has_value() && !time_result->isValid()) || bad_time_parse) {
+ fatal(MYNAME ": couldn't parse time from string '%s' with format '%s'.\n",
s, format);
- }
- return 0;
-}
+ }
+ if (time_result.has_value()) {
+ time = *time_result;
+ }
-time_t
-XcsvFormat::addhms(const char* s, const char* format)
-{
- time_t tt = 0;
- int hour = 0;
- int min = 0;
- int sec = 0;
-
- char* ampm = (char*) xmalloc(strlen(s) + 1);
- int ac = sscanf(s, format, &hour, &min, &sec, ampm);
- /* If no time format in arg string, assume AM */
- if (ac < 4) {
- ampm[0] = 0;
- }
- if (ac) {
- tt = ((tolower(ampm[0])=='p') ? 43200 : 0) + 3600 * hour + 60 * min + sec;
+ std::optional<QDate> date_result;
+ bool bad_date_parse = false;
+ int year_result = (stm.tm_year >= 70)? stm.tm_year + 1900 : stm.tm_year + 2000;
+ if (stm.tm_year >= 0 && stm.tm_mon >= 0 && stm.tm_mday >= 0) {
+ date_result = QDate(year_result, stm.tm_mon + 1, stm.tm_mday);
+ } else if (stm.tm_year >= 0 && stm.tm_mon >= 0) {
+ date_result = QDate(year_result, stm.tm_mon + 1, 1);
+ } else if (stm.tm_year >= 0) {
+ date_result = QDate(year_result, 1, 1);
+ } else if (!(stm.tm_year == -1 && stm.tm_mon == -1 && stm.tm_mday == -1)) {
+ bad_date_parse = true;
+ }
+ if ((date_result.has_value() && !date_result->isValid()) || bad_date_parse) {
+ fatal(MYNAME ": couldn't parse date from string '%s' with format '%s'.\n",
+ s, format);
+ }
+ if (date_result.has_value()) {
+ date = *date_result;
+ }
+ } else {
+ // Don't fuss for empty strings.
+ if (*s) {
+ warning("date parse of string '%s' with format '%s' failed.\n",
+ s, format);
+ }
}
- xfree(ampm);
-
- return tt;
}
QString
QString
XcsvFormat::writetime(const char* format, const gpsbabel::DateTime& t, bool gmt)
{
- return writetime(format, t.toTime_t(), gmt);
-}
-
-QString
-XcsvFormat::writehms(const char* format, time_t t, bool gmt)
-{
- static const std::tm no_time{};
- static const std::tm* stmp = &no_time;
-
- if (gmt) {
- stmp = gmtime(&t);
- } else {
- stmp = localtime(&t);
- }
-
- if (stmp == nullptr) {
- stmp = &no_time;
- }
-
- return QString::asprintf(format,
- stmp->tm_hour, stmp->tm_min, stmp->tm_sec,
- (stmp->tm_hour >= 12 ? "PM" : "AM"));
-}
-
-QString
-XcsvFormat::writehms(const char* format, const gpsbabel::DateTime& t, bool gmt)
-{
- return writehms(format, t.toTime_t(), gmt);
+ uint32_t tt = t.toTime_t();
+ return (tt == 0xffffffffU)? QString() : writetime(format, tt, gmt);
}
long
XcsvFormat::time_to_yyyymmdd(const QDateTime& t)
{
- QDate d = t.date();
+ QDate d = t.toUTC().date();
return d.year() * 10000 + d.month() * 100 + d.day();
}
break;
/* TIME CONVERSIONS ***************************************************/
- case XcsvStyle::XT_EXCEL_TIME:
+ case XcsvStyle::XT_EXCEL_TIME: {
/* Time as Excel Time */
- wpt->SetCreationTime(excel_to_timet(strtod(s, nullptr)));
- break;
+ bool ok;
+ double et = value.toDouble(&ok);
+ if (ok) {
+ wpt->SetCreationTime(0, excel_to_timetms(et));
+ parse_data->need_datetime = false;
+ } else if (!value.isEmpty()) {
+ warning("parse of string '%s' on line number %d as EXCEL_TIME failed.\n", s, line_no);
+ }
+ }
+ break;
case XcsvStyle::XT_TIMET_TIME: {
/* Time as time_t */
bool ok;
- wpt->SetCreationTime(value.toLongLong(&ok));
- if (!ok) {
+ long long tt = value.toLongLong(&ok);
+ if (ok) {
+ wpt->SetCreationTime(tt);
+ parse_data->need_datetime = false;
+ } else if (!value.isEmpty()) {
warning("parse of string '%s' on line number %d as TIMET_TIME failed.\n", s, line_no);
}
}
case XcsvStyle::XT_TIMET_TIME_MS: {
/* Time as time_t in milliseconds */
bool ok;
- wpt->SetCreationTime(0, value.toLongLong(&ok));
- if (!ok) {
+ long long tt = value.toLongLong(&ok);
+ if (ok) {
+ wpt->SetCreationTime(0, tt);
+ parse_data->need_datetime = false;
+ } else if (!value.isEmpty()) {
warning("parse of string '%s' on line number %d as TIMET_TIME_MS failed.\n", s, line_no);
}
}
break;
case XcsvStyle::XT_YYYYMMDD_TIME:
- wpt->SetCreationTime(yyyymmdd_to_time(value));
+ parse_data->utc_date = yyyymmdd_to_time(value);
break;
case XcsvStyle::XT_GMT_TIME:
- wpt->SetCreationTime(sscanftime(s, fmp.printfc.constData(), true));
+ sscanftime(s, fmp.printfc.constData(), parse_data->utc_date, parse_data->utc_time);
break;
case XcsvStyle::XT_LOCAL_TIME:
- if (!gpsbabel_testmode()) {
- wpt->creation_time = wpt->creation_time.addSecs(sscanftime(s, fmp.printfc.constData(), false));
- } else {
- /* Force constant time zone for test */
- wpt->creation_time = wpt->creation_time.addSecs(sscanftime(s, fmp.printfc.constData(), true));
- }
- break;
- /* Useful when time and date are in separate fields
- GMT / Local offset is handled by the two cases above */
- case XcsvStyle::XT_HMSG_TIME:
- case XcsvStyle::XT_HMSL_TIME:
- wpt->creation_time = wpt->creation_time.addSecs(addhms(s, fmp.printfc.constData()));
+ sscanftime(s, fmp.printfc.constData(), parse_data->local_date, parse_data->local_time);
break;
case XcsvStyle::XT_ISO_TIME:
case XcsvStyle::XT_ISO_TIME_MS:
- wpt->SetCreationTime(xml_parse_time(value));
+ wpt->SetCreationTime(QDateTime::fromString(value, Qt::ISODateWithMs));
+ parse_data->need_datetime = false;
break;
case XcsvStyle::XT_NET_TIME: {
bool ok;
- wpt->SetCreationTime(dotnet_time_to_qdatetime(value.toLongLong(&ok)));
- if (!ok) {
+ long long dnt = value.toLongLong(&ok);
+ if (ok) {
+ wpt->SetCreationTime(dotnet_time_to_qdatetime(dnt));
+ parse_data->need_datetime = false;
+ } else if (!value.isEmpty()) {
warning("parse of string '%s' on line number %d as NET_TIME failed.\n", s, line_no);
}
}
break;
- case XcsvStyle::XT_GEOCACHE_LAST_FOUND:
- wpt->AllocGCData()->last_found = yyyymmdd_to_time(value);
+ case XcsvStyle::XT_GEOCACHE_LAST_FOUND: {
+ QDate date;
+ date = yyyymmdd_to_time(value);
+#if (QT_VERSION < QT_VERSION_CHECK(5, 14, 0))
+ wpt->AllocGCData()->last_found = QDateTime(date);
+#else
+ wpt->AllocGCData()->last_found = date.startOfDay();
+#endif
break;
+ }
/* GEOCACHING STUFF ***************************************************/
case XcsvStyle::XT_GEOCACHE_DIFF:
}
}
+
+ if (parse_data.need_datetime) {
+ if (parse_data.utc_date.isValid() && parse_data.utc_time.isValid()) {
+ wpt_tmp->SetCreationTime(xcsv_adjust_time(parse_data.utc_date, parse_data.utc_time, false));
+ } else if (parse_data.local_date.isValid() && parse_data.local_time.isValid()) {
+ wpt_tmp->SetCreationTime(xcsv_adjust_time(parse_data.local_date, parse_data.local_time, true));
+ } else if (parse_data.utc_date.isValid()) {
+ wpt_tmp->SetCreationTime(xcsv_adjust_time(parse_data.utc_date, parse_data.utc_time, false));
+ } else if (parse_data.local_date.isValid()) {
+ wpt_tmp->SetCreationTime(xcsv_adjust_time(parse_data.local_date, parse_data.local_time, true));
+ } else if (parse_data.utc_time.isValid()) {
+ wpt_tmp->SetCreationTime(xcsv_adjust_time(parse_data.utc_date, parse_data.utc_time, false));
+ } else if (parse_data.local_time.isValid()) {
+ wpt_tmp->SetCreationTime(xcsv_adjust_time(parse_data.local_date, parse_data.local_time, true));
+ }
+ }
+
// If XT_LAT_DIR(XT_LON_DIR) was an input field, and the latitude(longitude) is positive,
// assume the latitude(longitude) was the absolute value and take the sign from XT_LAT_DIR(XT_LON_DIR).
if (parse_data.lat_dir_positive.has_value() && !(*parse_data.lat_dir_positive) && (wpt_tmp->latitude > 0.0)) {
/* TIME CONVERSIONS**************************************************/
case XcsvStyle::XT_EXCEL_TIME:
/* creation time as an excel (double) time */
- buff = QString::asprintf(fmp.printfc.constData(), timet_to_excel(wpt->GetCreationTime().toTime_t()));
+ if (wpt->GetCreationTime().isValid()) {
+ buff = QString::asprintf(fmp.printfc.constData(), timetms_to_excel(wpt->GetCreationTime().toMSecsSinceEpoch()));
+ }
break;
case XcsvStyle::XT_TIMET_TIME:
/* time as a time_t variable in seconds */
- buff = QString::asprintf(fmp.printfc.constData(), wpt->GetCreationTime().toSecsSinceEpoch());
+ if (wpt->GetCreationTime().isValid()) {
+ buff = QString::asprintf(fmp.printfc.constData(), wpt->GetCreationTime().toSecsSinceEpoch());
+ }
break;
case XcsvStyle::XT_TIMET_TIME_MS:
/* time as a time_t variable in milliseconds */
- buff = QString::asprintf(fmp.printfc.constData(), wpt->GetCreationTime().toMSecsSinceEpoch());
+ if (wpt->GetCreationTime().isValid()) {
+ buff = QString::asprintf(fmp.printfc.constData(), wpt->GetCreationTime().toMSecsSinceEpoch());
+ }
break;
case XcsvStyle::XT_YYYYMMDD_TIME:
- buff = QString::asprintf(fmp.printfc.constData(), time_to_yyyymmdd(wpt->GetCreationTime()));
+ if (wpt->GetCreationTime().isValid()) {
+ buff = QString::asprintf(fmp.printfc.constData(), time_to_yyyymmdd(wpt->GetCreationTime()));
+ }
break;
case XcsvStyle::XT_GMT_TIME:
buff = writetime(fmp.printfc.constData(), wpt->GetCreationTime(), true);
case XcsvStyle::XT_LOCAL_TIME:
buff = writetime(fmp.printfc.constData(), wpt->GetCreationTime(), false);
break;
- case XcsvStyle::XT_HMSG_TIME:
- buff = writehms(fmp.printfc.constData(), wpt->GetCreationTime(), true);
- break;
- case XcsvStyle::XT_HMSL_TIME:
- buff = writehms(fmp.printfc.constData(), wpt->GetCreationTime(), false);
- break;
case XcsvStyle::XT_ISO_TIME:
- buff = writetime("%Y-%m-%dT%H:%M:%SZ", wpt->GetCreationTime(), true);
+ if (wpt->GetCreationTime().isValid()) {
+ buff = wpt->GetCreationTime().toUTC().toString(Qt::ISODate);
+ }
break;
case XcsvStyle::XT_ISO_TIME_MS:
- buff = wpt->GetCreationTime().toPrettyString();
+ if (wpt->GetCreationTime().isValid()) {
+ buff = wpt->GetCreationTime().toPrettyString();
+ }
+ break;
+ case XcsvStyle::XT_NET_TIME:
+ if (wpt->GetCreationTime().isValid()) {
+ buff = QString::number(qdatetime_to_dotnet_time(wpt->GetCreationTime()));
+ }
break;
case XcsvStyle::XT_GEOCACHE_LAST_FOUND:
buff = QString::asprintf(fmp.printfc.constData(), time_to_yyyymmdd(wpt->gc_data->last_found));
if (xcsv_file->gps_datum_idx < 0) {
fatal(MYNAME ": datum \"%s\" is not supported.", qPrintable(datum_name));
}
+
+ utc_offset = (opt_utc == nullptr)? 0 : xstrtoi(opt_utc, nullptr, 10) * SECONDS_PER_HOUR;
}
void
#include <utility> // for move
#include <QByteArray> // for QByteArray
+#include <QDate> // for QDate
#include <QDateTime> // for QDateTime
#include <QHash> // for QHash
#include <QList> // for QList
#include <QString> // for QString
#include <QStringList> // for QStringList
+#include <QTime> // for QTime
#include <QVector> // for QVector
+#include <QtGlobal> // for qRound64
#include "defs.h"
#include "format.h"
XT_GPS_SAT,
XT_GPS_VDOP,
XT_HEART_RATE,
- XT_HMSG_TIME,
- XT_HMSL_TIME,
XT_ICON_DESCR,
XT_IGNORE,
XT_INDEX,
UrlLink* link_{nullptr};
std::optional<bool> lat_dir_positive;
std::optional<bool> lon_dir_positive;
+ QDate local_date;
+ QTime local_time;
+ QDate utc_date;
+ QTime utc_time;
+ bool need_datetime{true};
};
/* Constants */
}
/* convert excel time (days since 1900) to time_t and back again */
- static constexpr double excel_to_timet(double a)
+ static constexpr qint64 excel_to_timetms(double a)
{
- return (a - 25569.0) * 86400.0;
+ return qRound64((a - 25569.0) * 86400000.0);
}
- static constexpr double timet_to_excel(double a)
+ static constexpr double timetms_to_excel(qint64 a)
{
- return (a / 86400.0) + 25569.0;
+ return (a / 86400000.0) + 25569.0;
}
/* Member Functions */
- static QDateTime yyyymmdd_to_time(const QString& s);
- static time_t sscanftime(const char* s, const char* format, bool gmt);
- static time_t addhms(const char* s, const char* format);
+ static QDate yyyymmdd_to_time(const QString& s);
+ QDateTime xcsv_adjust_time(const QDate date, const QTime time, bool is_localtime) const;
+ static void sscanftime(const char* s, const char* format, QDate& date, QTime& time);
+ static QTime addhms(const char* s, const char* format);
static QString writetime(const char* format, time_t t, bool gmt);
static QString writetime(const char* format, const gpsbabel::DateTime& t, bool gmt);
static QString writehms(const char* format, time_t t, bool gmt);
char* prefer_shortnames = nullptr;
char* xcsv_urlbase = nullptr;
char* opt_datum = nullptr;
+ char* opt_utc = nullptr;
+ int utc_offset{};
QString intstylefile;
"datum", &opt_datum, "GPS datum (def. WGS 84)",
nullptr, ARGTYPE_STRING, ARG_NOMINMAX, nullptr
},
+ {
+ "utc", &opt_utc, "Write timestamps with offset x to UTC time",
+ nullptr, ARGTYPE_INT, "-14", "+14", nullptr
+ },
};
};
</section>
<section xml:id="style_def_yyyymmdd">
<title>YYYYMMDD_TIME</title>
- <para>YYYYMMDD_TIME is the waypoint's creation time, if any. It's a single
+ <para>YYYYMMDD_TIME is the waypoint's creation time in UTC, if any. It's a single
decimal field containing four digits of year, two digits of month,
and two digits of date. Internally it is a LONG INTEGER and thus
requires a LONG INTEGER printf conversion.
<title>GMT_TIME</title>
<para>GMT_TIME is the waypoint's creation time, in UTC time zone. It uses the
strptime conversion format tags.
+ It can be used to parse/print a date and time in one column,
+ or a date in one column and a time in another column. If used to parse a date and a
+ time in separate columns the date and time can be in either order.
</para>
- <para>example:
-</para>
- <screen>IFIELD GMT_TIME,"","%m/%d/%Y %I:%M:%D %p"
+<para>example with a a date followed by a time using a 12 hour clock and an AM/PM indication:</para>
+<screen>IFIELD GMT_TIME,"","%m/%d/%Y %I:%M:%S %p"
+</screen>
+<para>example with a a date followed by a time using a 24 hour clock:</para>
+<screen>IFIELD GMT_TIME,"","%Y/%m/%d"
+IFIELD GMT_TIME,"","%H:%M:%S"
</screen>
- <para>Search the web for 'strptime man page' for details strptime, but one
+<para>Search the web for 'strptime man page' for details strptime, but one
such page can be found at
-
-
-
-
-
-
-
- <link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://www.die.net/doc/linux/man/man3/strptime.3.html">http://www.die.net/doc/linux/man/man3/strptime.3.html</link></para>
+ <link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://www.die.net/doc/linux/man/man3/strptime.3.html">http://www.die.net/doc/linux/man/man3/strptime.3.html</link></para>
</section>
<section xml:id="style_def_localtime">
<title>LOCAL_TIME</title>
<para>LOCAL_TIME is the waypoint's creation time, in the local
- time zone. It uses strptime conversion format tags. See GMT_TIME for a
- reference.
-</para>
- <para>example:
+ time zone. It uses strptime conversion format tags.
+ It can be used to parse/print a date and time in one column,
+ or a date in one column and a time in another column. If used to parse a date and a
+ time in separate columns the date and time can be in either order.
+ See GMT_TIME for examples and a reference.
</para>
- <screen>IFIELD LOCAL_TIME,"","%y-%m-%d"
-</screen>
- </section>
- <section xml:id="style_def_hmsgtime">
- <title>HMSG_TIME</title>
- <para>HMSG_TIME parses up to three time parts and am/pm string to add
- this value to the previously parsed *_TIME field that contains
- only a date. On output, will print the time in UTC.
-</para>
- <para>example:
-</para>
- <screen>IFIELD HMSG_TIME,"","%02d:%02d:%02d %s"
-</screen>
- </section>
- <section xml:id="style_def_hmsltime">
- <title>HMSL_TIME</title>
- <para>HMSG_TIME parses up to three time parts and am/pm string to add
- this value to the previously parsed *_TIME field that contains
- only a date. On output, will print the time in local time.
-</para>
- <para>example:
-</para>
- <screen>IFIELD HMSL_TIME,"","%dh%dm"
-</screen>
</section>
<section xml:id="style_def_isotime">
<title>ISO_TIME</title>
<para>
-This option specifies the local time zone to use when writing times. It
-is specified as an offset from Universal Coordinated Time (UTC) in hours.
-Valid values are from -23 to +23.
+This option specifies the local time zone to use when reading and writing times. It
+specifies a Universal Coordinated Time (UTC) offset in hours. For example, in the
+winter in Sweden the UTC offset is UTC+1, which corresponds to an option utc=1.
+Valid values are from -14 to +14.
</para>